Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support next.config.js redirects, rewrites, headers #150

Closed
scopsy opened this issue Jun 26, 2020 · 10 comments
Closed

Support next.config.js redirects, rewrites, headers #150

scopsy opened this issue Jun 26, 2020 · 10 comments
Labels
fixed in upcoming release This bug is fixed in the neext major release of the plugin priority: medium rewrite candidate type: feature code contributing to the implementation of a feature and/or user facing functionality

Comments

@scopsy
Copy link

scopsy commented Jun 26, 2020

First of all, thank you for the amazing work with this package!

Currently when defining experimental rewrites in next.config.js they are not respected in netlify and throw 404 error from netlify. Any chance they can be supported?

example of the config file:

module.exports = {
  target: 'serverless',
  experimental: {
    redirects() {
      const redirects = [
        {
          // Redirect root link with trailing slash to non-trailing slash, avoids 404 - See https://github.com/vercel/next.js/discussions/10651#discussioncomment-8270
          source: '/:locale/',
          destination: '/:locale',
          permanent: process.env.NEXT_PUBLIC_APP_STAGE !== 'development', // Do not use permanent redirect locally to avoid browser caching when working on it
        },
        {
          // Redirect link with trailing slash to non-trailing slash (any depth), avoids 404 - See https://github.com/vercel/next.js/discussions/10651#discussioncomment-8270
          source: '/:locale/:path*/',
          destination: '/:locale/:path*',
          permanent: true
        },
      ];

      return redirects;
    },
    rewrites() {
      const rewrites = [
        {
          source: '/',
          destination: '/api/autoRedirectToLocalisedPage',
        },
        {
          source: `/:locale((?!${noRedirectBasePaths.join('|')})[^/]+)(.*)`,
          destination: '/api/autoRedirectToLocalisedPage',
        },
      ];

      return rewrites;
    },
  },
};

@FinnWoelm
Copy link

Hey @scopsy,

Thank you for the kind words and for filing this issue to make next-on-netlify better 🙂

I had a closer look at the NextJS experimental syntax for redirects and rewrites as well as the limitations that apply to redirects on Netlify. There are a couple issues:

Netlify's redirect syntax is a lot more narrow than the one used by NextJS

Netlify only supports redirects with plain text, with parameter placeholders (/:id/:slug/:abc/...), and/or with match-all splats (/some/path/*). For example, the last rewrite you shared would not work on Netlify:

`/:locale((?!${noRedirectBasePaths.join('|')})[^/]+)(.*)`

There is no direct way to express that in a Netlify-compatible way. With Netlify, you would probably define it as a catch-all /* rewrite and position it after all other rewrites and redirects. Because Netlify only uses the first redirect/rewrite it finds and because of shadowing, Netlify would not apply the rewrite in any case where the user requests a page that actually exists.

So it's possible to express the same rewrite in Netlify, but I can't think of a way to automatically translate a redirect like the one you shared into the Netlify equivalent, correctly deciding if the rewrite should be at the very top or the very bottom of the list.

Netlify only redirects/rewrites once per request

I need to double check this, but my understanding is that Netlify only redirects or rewrites once per request. All server-side rendered pages and all pages with dynamic paths already require one redirect. For example, we may have a SSRed page called /users. That page gets turned into a serverless function and next-on-netlify creates a redirect for /users to /.netlify/functions/next_users . Now, if we try to add a redirect for /allusers to /users, Netlify will perform only that redirect, but not the /users -> /.netlify/functions/next_users one. It will try to serve users.html from the publish directory (out_public), not find it, and return 404.

One way to correct for that would be to evaluate the redirects at build-time. For example: next-on-netlify sees a redirect for /allusers to /users and next-on-netlify knows that we need to redirect /users to /.netlify/functions/next_users, so next-on-netlify writes the redirect as /allusers > /.netlify/functions/next_users. But that only works if the redirects are static. As soon as they are dyamic, using /:params or *-splat, this kind of evaluation becomes very difficult/impossible.

Next Steps

What do you think? Do you have ideas for how this could work? In your specific case, you could just work around it for now: The first two redirects are not needed for Netlify (because they normalize the URLs and trailing slashes anyway) and the last two rewrites you could manually add as one single rewrite in your netlify.toml:

[[redirects]]
  from = "/*"
  to = "/.netlify/functions/next_api_autoRedirectToLocalisedPage"
  status = 200

It would catch any unmatched path and call your API endpoint. Not what you were hoping for, I'm sure, but that's my best idea at the moment.

Let me know what you think!
- Finn

@lindsaylevine lindsaylevine pinned this issue Feb 16, 2021
@lindsaylevine lindsaylevine unpinned this issue Mar 2, 2021
@joaogarin
Copy link

This is now fully supported (not experimental) in Nextjs. is this something that will be eventually added / supported? I would like to consider moving an app to netlify but currently it does use nextjs redirects and rewrites and so would be tricky not having those work anymore if I decide to move it =) thank you! happy netlify client ;)

@lindsaylevine lindsaylevine transferred this issue from netlify/next-on-netlify Mar 16, 2021
@lindsaylevine lindsaylevine added priority: medium type: feature code contributing to the implementation of a feature and/or user facing functionality labels Mar 19, 2021
@lindsaylevine lindsaylevine changed the title Support experimental next.config.js redirects and rewrites Support next.config.js redirects, rewrites, headers Mar 26, 2021
@odenirdev
Copy link

i have the same problem of @scopsy

@odenirdev
Copy link

i need the rewrites next.config.js

@TimNZ
Copy link

TimNZ commented Sep 14, 2021

To be clear: custom header in next.config.js are not supported?

headers: async () => {
	return [
		{
		source: "/(.*\\.(?:jpg|jpeg|png|gif))",
		headers: [
		{
			key: "Cache-Control",
			value: "public, max-age=3600",
		},
	],
	},
	]
	},

@ascorbic ascorbic added the fixed in upcoming release This bug is fixed in the neext major release of the plugin label Oct 3, 2021
@tbgse
Copy link

tbgse commented Oct 13, 2021

Hi all,

jumping on this issue because we're facing a possibly related problem: We want to create a rewrite to our api routes using the netlify.toml file, looking like this:

[[redirects]]
  from = "/custom-api-route/*"
  to = ""/api/:splat"
  status = 200

However, it seems like all of the requests to /custom-api/* end up with a 404 status. Possibly because the nextjs api routes itself are already configured as rewrites in the generated toml file by the nextjs plugin for netlify?

Is this a known issue or am I doing something wrong? When I configure non-api route redirects in the netlify.toml file, everything works as expected 🤔

@ascorbic
Copy link
Contributor

ascorbic commented Nov 1, 2021

Fixed in version 4

@ascorbic ascorbic closed this as completed Nov 1, 2021
@wildabeast
Copy link

wildabeast commented Feb 7, 2023

I cannot for the life of me get a CSP header set on the root page of my nextjs/netlify app.

next.config.js:

    async headers() {
      return [
        {
          source: '/',
          headers: [
            {
              key: 'Content-Security-Policy',
              value: "default-src 'self';",
            },
          ]
        }
      ];
    },

netlify.toml

[[headers]]
  for = "/*"
  [headers.values]
    Content-Security-Policy = "default-src 'self';"

_headers

/*
  Content-Security-Policy: default-src 'self';

Any guidance? thx

@adshodgson
Copy link

I cannot for the life of me get a CSP header set on the root page of my nextjs/netlify app.

next.config.js:

    async headers() {
      return [
        {
          source: '/',
          headers: [
            {
              key: 'Content-Security-Policy',
              value: "default-src 'self';",
            },
          ]
        }
      ];
    },

netlify.toml

[[headers]]
  for = "/*"
  [headers.values]
    Content-Security-Policy = "default-src 'self';"

_headers

/*
  Content-Security-Policy: default-src 'self';

Any guidance? thx

Having similar issue, any resolution?

@Hexi1997
Copy link

I cannot for the life of me get a CSP header set on the root page of my nextjs/netlify app.
next.config.js:

    async headers() {
      return [
        {
          source: '/',
          headers: [
            {
              key: 'Content-Security-Policy',
              value: "default-src 'self';",
            },
          ]
        }
      ];
    },

netlify.toml

[[headers]]
  for = "/*"
  [headers.values]
    Content-Security-Policy = "default-src 'self';"

_headers

/*
  Content-Security-Policy: default-src 'self';

Any guidance? thx

Having similar issue, any resolution?

I cannot for the life of me get a CSP header set on the root page of my nextjs/netlify app.
next.config.js:

    async headers() {
      return [
        {
          source: '/',
          headers: [
            {
              key: 'Content-Security-Policy',
              value: "default-src 'self';",
            },
          ]
        }
      ];
    },

netlify.toml

[[headers]]
  for = "/*"
  [headers.values]
    Content-Security-Policy = "default-src 'self';"

_headers

/*
  Content-Security-Policy: default-src 'self';

Any guidance? thx

Having similar issue, any resolution?

Hey, Have you solved this problem? I encountered it too

serhalp pushed a commit that referenced this issue Apr 5, 2024
* fix: handle parallel routes default layout

* Fix tests

* Check that it's app router

* Add fs check

* Don't worry about missing default.meta
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixed in upcoming release This bug is fixed in the neext major release of the plugin priority: medium rewrite candidate type: feature code contributing to the implementation of a feature and/or user facing functionality
Projects
None yet
Development

No branches or pull requests