next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Rewrites in middleware override next.config rewrites

Open Dreamer-Paul opened this issue 1 year ago • 3 comments

Link to the code that reproduces this issue

https://codesandbox.io/p/sandbox/nextjs-middleware-rewrite-bug-wjlcns

To Reproduce

  1. Add rewrite rules in next.config.js like this:
const nextConfig = {
  async rewrites() {
    return [
      {
        source: "/paul/:slug",
        destination: "https://paul.ren/api/:slug",
      },
    ];
  },
};
  1. Add rewrite rules in middleware.js like this:
import { NextResponse } from "next/server";

export function middleware(request) {
  const nextUrl = request.nextUrl;
  nextUrl.pathname = `/test/${nextUrl.pathname}`;

  const response = NextResponse.rewrite(nextUrl);

  return response;
}

export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};
  1. Open projectUrl/paul/note in the browser, got 404 http code and err message.

Current vs. Expected behavior

Following the steps from the previous section, I expected to see the content of the proxied website normally, but i observed got a 404 error instead.

This is based on my reading of the relevant instructions in the middleware documentation, which has explicitly stated that the next.config.js has the highest priority.

https://nextjs.org/docs/app/building-your-application/routing/middleware#matching-paths

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 22.6.0: Wed Jul  5 22:17:35 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T8112
  Available memory (MB): 24576
  Available CPU cores: 8
Binaries:
  Node: 20.8.0
  npm: 10.1.0
  Yarn: N/A
  pnpm: 9.4.0
Relevant Packages:
  next: 14.2.4 // Latest available version is detected (14.2.4).
  eslint-config-next: 14.2.4
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.5.2
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Middleware

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

No response

Dreamer-Paul avatar Jun 27 '24 15:06 Dreamer-Paul

The codes below are write in the middleware seems to achieve the result I need, but is it reasonable that the priority of middleware's rewrites is higher than next.config.js?

export function middleware(request) {
  if (request.nextUrl.pathname.startsWith("/paul")) {
    const response = NextResponse.rewrite(`https://paul.ren/${request.nextUrl.pathname.replace("/paul", "")}`);

    return response;
  }

  ...
}

Dreamer-Paul avatar Jun 27 '24 17:06 Dreamer-Paul

This is based on my reading of the relevant instructions in the middleware documentation, which has explicitly stated that the next.config.js has the highest priority.

  1. headers from next.config.js
  2. redirects from next.config.js
  3. Middleware (rewrites, redirects, etc.)
  4. beforeFiles (rewrites) from next.config.js
  5. Filesystem routes (public/, _next/static/, pages/, app/, etc.)
  6. afterFiles (rewrites) from next.config.js
  7. Dynamic Routes (/blog/[slug])
  8. fallback (rewrites) from next.config.js

next.config.js rewrites are lower priority than middleware, so this is not a bug. It looks like it would work if you used redirect instead. Is that an option?

If using redirects isn't an option, you could also try changing your matcher config to exclude the /paul route:

  matcher: ["/((?!api|_next/static|_next/image|favicon.ico|paul).*)"],

ijxy avatar Jun 29 '24 17:06 ijxy

next.config.js rewrites are lower priority than middleware, so this is not a bug. It looks like it would work if you used redirect instead. Is that an option?

Sorry, it seems that I didn't read thoroughly enough. The next.config.js file only gives the highest priority to redirects, not the rewrites. However, I don't understand why they designed it this way. Could this be somewhat misleading? Although I found that using rewrites in middleware is actually more flexible than in next.config.js.

Dreamer-Paul avatar Jun 30 '24 04:06 Dreamer-Paul

The fact that beforeFiles doesn't run before middleware files is a bit confusing.

BayanBennett avatar Sep 06 '24 00:09 BayanBennett