Netlify Redirect or Rewrite for Gatsby Wildcard Path - reactjs

So I've already implemented a wildcard path on my gatsby-node.js file:
exports.onCreatePage = async ({ page, actions }) => {
const { createPage } = actions
if (page.path.match(/^\/my-path/)) {
page.matchPath = "/my-path/*"
createPage(page)
}
}
and this works fine when I am running the site locally (in development). i.e., if i provide /my-path/anything123 or /my-path/asdfasdfasdf, both will lead to a rendering of the component I've created in my Gatsby project under pages/my-path.tsx.
Now we come to my problem. When I deploy my site to Netlify, I don't get the same behavior as in development. Can behavior like this be handled with a redirect or rewrite in Netlify? I don't want to lose the content in what comes after /my-path/, as in reality I'm using it to parse an id, i.e. if the URL in the browser is /my-path/123, I want to be able to see that 123 in window.location.href, and parse it with some logic in my-path.tsx.
I hope this is clear. Appreciate anyone who can help or guide me in the right direction!

Of course after writing this all up the answer becomes clear... I tried it, and it works! for the example I was providing, the following redirect would work in your netlify.toml file:
[[redirects]]
from = "/my-path/*"
to = "/my-path"
status = 200
force = true
So it essentially has to match 1:1 with the rules you define in gatsby-node.js.

Related

Is there a way to rename automatically generated routes JSON file in Next.js?

I have a problem, when I click to go to the /analytics page on my site, adblockers block the analytics.json file that's being requested by Next.js as they think it's an analytics tracker (it's not, it's a page listing analytics products).
Is there a way to rename the route files Next.js uses when navigating to server-side rendered pages on the client-side?
I want to either obfuscate the names so they're not machine readable, or have a way to rename them all.
Any help appreciated.
With thanks to #gaston-flores I've managed to get something working.
In my instance /analytics is a dynamic page for a category, so I moved my pages/[category]/index.tsx file to pages/[category]/category.tsx and added the following rewrite:
// next.config.js
module.exports = {
async rewrites() {
return [
{
source: "/:category",
destination: "/:category/category",
},
];
},
};
This now gets the category.json file rather than analytics.json, which passes the adblockers checks and renders as expected.
Note that due to having a dynamic file name in the pages/[category] directory (pages/[category]/[product].tsx), I had to move that to pages/[category]/product/[product].tsx as I was seeing the /analytics page redirected to /analytics/category for some reason without this tweak.

getInitialProps causing ERR_TOO_MANY_REDIRECTS error on my live site, but not on my local version

So, I've been trying to implement cookies on my website, to keep track of a list of JavaScript objects, so the page stays consistent when the user comes back to it. I've been following this tutorial here.
On my local machine, using npm run dev on localhost:3000, it works absolutely perfect. However, when I push the commit to GitHub, it builds on Vercel without any issue, but when I try and access the live website on the internet, it gives me a 'ERR_TOO_MANY_REDIRECTS' error.
I'm pretty confused as to why it would work perfectly fine on my locally hosted site, but freaks out and does not work when it's put into production.
I think I have narrowed the problem down to getInitialProps because when I comment out the implementation in my index.js file, it still doesn't work, but when I comment out getInitialProps, it works again.
Here is the code I think may be the problem.
Home.getInitialProps = async ({req, res}) => {
const data = parseCookies(req)
if (res) {
if (Object.keys(data).length === 0 && data.constructor === Object) {
res.writeHead(301, { Location: "/" })
res.end()
}
}
return {
data: data && data,
}
}
And here is the code for that parseCookies method, which is imported as
import { parseCookies } from "../helpers/index"
within my index.js
import cookie from "cookie"
export function parseCookies(req) {
return cookie.parse(req ? req.headers.cookie || "" : document.cookie)
}
I'm super confused at this point, I've walked myself through the code a dozen times now and still have no idea what I might be doing wrong. Any help would be much appreciated! And please lemme know if there's anymore info I can provide!
The ERR_TOO_MANY_REDIRECTS error occurs because Object.keys(data).length === 0 && data.constructor === Object returns true when no cookies are set and you access the homepage. When this happens the redirect takes you back to / (the homepage) which then makes the check again and a new redirect occurs, and so on.
Locally, you probably have cookies set, so you don't experience the issue. However, when you access the website hosted on Vercel, no cookies are present initially, which triggers the infinite redirect cycle.
To fix the issue simply remove the logic from the homepage, since that's the redirect destination. You can still have it on other pages and redirect to the homepage, though.

Authentication to serve static files on Next.js?

So, I looked for a few authentication options for Next.js that wouldn't require any work on the server side of things. My goal was to block users from entering the website without a password.
I've set up a few tests with NextAuth (after a few other tries) and apparently I can block pages with sessions and cookies, but after a few hours of research I still can't find how I would go about blocking assets (e.g. /image.png from the /public folder) from non-authenticated requests.
Is that even possible without a custom server? Am I missing some core understanding here?
Thanks in advance.
I did stumble upon this problem too. It took my dumbass a while but i figured it out in the end.
As you said - for auth you can just use whatever. Such as NextAuth.
And for file serving: I setup new api endpoint and used NodeJS magic of getting the file and serving it in pipe. It's pretty similar to what you would do in Express. Don't forget to setup proper head info in your response.
Here is little snippet to demonstrate (typescript version):
import { NextApiRequest, NextApiResponse } from 'next'
import {stat} from "fs/promises"
import {createReadStream, existsSync} from "fs"
import path from "path"
import mime from "mime"
//basic nextjs api
export default async function getFile (req: NextApiRequest, res: NextApiResponse) {
// Dont forget to auth first!1!!!
// for this i created folder in root folder (at same level as normal nextjs "public" folder) and the "somefile.png" is in it
const someFilePath = path.resolve('./private/somefile.png');
// if file is not located in specified folder then stop and end with 404
if (! existsSync(someFilePath)) return res.status(404);
// Create read stream from path and now its ready to serve to client
const file = createReadStream(path.resolve('./private/somefile.png'))
// set cache so its proper cached. not necessary
// 'private' part means that it should be cached by an invidual(= is intended for single user) and not by single cache. More about in https://stackoverflow.com/questions/12908766/what-is-cache-control-private#answer-49637255
res.setHeader('Cache-Control', `private, max-age=5000`);
// set size header so browser knows how large the file really is
// im using native fs/promise#stat here since theres nothing special about it. no need to be using external pckages
const stats = await stat(someFilePath);
res.setHeader('Content-Length', stats.size);
// set mime type. in case a browser cant really determine what file its gettin
// you can get mime type by lot if varieties of methods but this working so yay
const mimetype = mime.getType(someFilePath);
res.setHeader('Content-type', mimetype);
// Pipe it to the client - with "res" that has been given
file.pipe(res);
}
Cheers

Next.js: How can we have dynamic routing redirect to static pages?

Using Next.js , I currently have an app with a single entry point in the form of /pages/[...slug]/index.ts
It contains a getServerSideProps function which analyses the slug and decide upon a redirection
In some cases a redirection is needed, but it will always be towards a page that can be statically rendered. Example: redirect /fr/uid towards /fr/blog/uid which can be static.
In other cases the slug already is the url of a page that can be static.
How can I mix this dynamic element with a static generation of all pages?
Thanks a lot for your help!
If I understood you problem correctly, you cannot use getServerSideProps if you are going to export a static site.
You have two solutions:
Configure your redirection rules in your web hosting solution (i.e. Amazon S3/CloudFront).
Create client-side redirects (when _app.tsx mounts you can check if router.asPath matches any of the redirection you would like to have configured.
Please remember that the first solution is more correct (as 301 redirects from the browser) for SEO purposes.
EDIT: #juliomalves rightly pointed out OP is looking at two different things: redirection, and hybrid builds.
However, question should be clarified a bit more to really be able to solve his problem.
Because you will need to host a web-server for SSR, you can leverage Next.js 9.5 built-in redirection system to have permanent server-side redirects.
When it comes to SSR vs SSG, Next.js allows you to adopt a hybrid approach, by giving you the possibility of choosing with Data Fetching strategy to adopt.
In case you are using AWS CloudFront, then you can redirect with CloudFront Functions.
CloudFront Functions is ideal for lightweight, short-running functions for use cases like the following:
URL redirects or rewrites – You can redirect viewers to other pages based on information in the request, or rewrite all requests from one path to another.
Here is what we are using to redirect clients (e.g. Native App, Google search index, etc.) to new location when NextJS page was moved or removed.
// NOTE: Choose "viewer request" for event trigger when you associate this function with CloudFront distribution.
function makeRedirectResponse(location) {
var response = {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
'location': { value: location }
}
};
return response;
}
function handler(event) {
var mappings = [
{ from: "/products/decode/app.html", to: '/products/decode.html' },
{ from: "/products/decode/privacy/2021_01_25.html", to: '/products/decode/privacy.html' }
];
var request = event.request;
var uri = request.uri;
for (var i = 0; i < mappings.length; i++) {
var mapping = mappings[i]
if (mapping.from === uri) {
return makeRedirectResponse(mapping.to)
}
}
return request;
}

Error while using searchKitManager in React

I am trying to use the searchKitManager inside react-admin I provided the parameters etc according to the docs but when I run the code it throws errors. Here is how the code works
React Admin is running on http://localhost:3000
Golang backend is running on http://localhost:3006
ElasticSearch is running on http://localhost:9200
When data is inserted in mysql database using golang code it is also inserted in elasticsearch later on in one of my display component I call the above searchkitManager as follows
let apiUrl= 'http://localhost:9200/donate' // what link should I pass, url to elasticsearch or url to my backend
const searchkit = new SearchkitManager('/', {
searchUrlPath: `${apiUrl}/_search`,
});
This code will throw 404 Not Found or 400 Bad Request error but the API works in postman
if I change the above link to
let apiUrl= 'http://localhost:9200/donate' // what link should I pass, url to elasticsearch or url to my backend
const searchkit = new SearchkitManager('/', {
searchUrlPath: `${apiUrl}/_doc/`,
});
I am not getting anything at all sometimes it no error in console and sometimes 400 Bad Request or 405 Post Not Allowed
One last thing the link I am providing as for searchUrlPath should be like that or not? or should I pass the apiUrl in place of /? I tried that as well but just to make sure.
Any kind of help will be really appreciated.
Try doing this:
const elasticSearchUrl = 'http://localhost:9200/<your_index>';
const searchkit = new SearchkitManager(elasticSearchUrl );

Resources