nextjs - 💡(How to fix) Fix Standalone mode: NextResponse.rewrite() in middleware returns 307 instead of serving rewritten content [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#91845Fetched 2026-04-08 01:20:39
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
labeled ×2commented ×1subscribed ×1

Code Example

git clone https://github.com/idatawebapp/nextjs-standalone-rewrite-bug
   cd nextjs-standalone-rewrite-bug
   npm install

---

npm run dev
   curl -s -D - http://localhost:3000/ | head -3
   # HTTP/1.1 200 OK — page content served correctly

---

npm run build
   cp -r .next/static .next/standalone/.next/
   PORT=3000 HOSTNAME=127.0.0.1 node .next/standalone/server.js
   curl -s -D - http://localhost:3000/ | grep "HTTP/\|location\|x-middleware"

---

HTTP/1.1 307 Temporary Redirect
   x-middleware-rewrite: http://localhost:3000/en
   location: /

---

Operating System:
  Platform: linux
  Arch: x64
  Version: #38-Ubuntu SMP PREEMPT_DYNAMIC
  Available memory (MB): 14297
  Available CPU cores: 10
Binaries:
  Node: 24.14.0
  npm: 11.11.1
Next.js: 16.2.1
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/idatawebapp/nextjs-standalone-rewrite-bug

To Reproduce

  1. Clone the reproduction repo:

    git clone https://github.com/idatawebapp/nextjs-standalone-rewrite-bug
    cd nextjs-standalone-rewrite-bug
    npm install
  2. Dev server (works correctly):

    npm run dev
    curl -s -D - http://localhost:3000/ | head -3
    # HTTP/1.1 200 OK — page content served correctly
  3. Standalone server (broken):

    npm run build
    cp -r .next/static .next/standalone/.next/
    PORT=3000 HOSTNAME=127.0.0.1 node .next/standalone/server.js
    curl -s -D - http://localhost:3000/ | grep "HTTP/\|location\|x-middleware"

    Result:

    HTTP/1.1 307 Temporary Redirect
    x-middleware-rewrite: http://localhost:3000/en
    location: /

    The standalone server returns 307 + location to the client instead of processing the rewrite internally. This causes an infinite redirect loop in the browser.

Current vs. Expected behavior

Current: In standalone mode, NextResponse.rewrite() from middleware produces a 307 redirect with location: / sent to the client. The x-middleware-rewrite header is present but the server doesn't process it internally.

Expected: The standalone server should process x-middleware-rewrite internally (like the dev server does) and return 200 with the rewritten page content. The rewrite should be transparent to the client.

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #38-Ubuntu SMP PREEMPT_DYNAMIC
  Available memory (MB): 14297
  Available CPU cores: 10
Binaries:
  Node: 24.14.0
  npm: 11.11.1
Next.js: 16.2.1

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

Middleware, Output (standalone)

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

next build (production)

Additional context

  • The reproduction uses next-intl v4.8.3 with localePrefix: 'as-needed', but the bug is in the Next.js standalone server not processing x-middleware-rewrite when a location header is also present.
  • Even a custom middleware that directly calls NextResponse.rewrite(new URL('/en', request.url)) produces the same 307 behavior in standalone mode.
  • Setting __NEXT_PRIVATE_ORIGIN=http://127.0.0.1:3000 does not fix the issue.
  • When deployed behind nginx with X-Forwarded-Proto: https, the rewrite URL becomes https://localhost:3000/en, causing EPROTO errors since the standalone server is HTTP-only.

Related issues:

  • #55648 (307 redirect loop with locale + middleware, v13)
  • #84504 (forwarded server actions with middleware rewrites)

extent analysis

Fix Plan

To fix the issue with the Next.js standalone server not processing x-middleware-rewrite internally, we need to modify the server to handle rewrites correctly.

Here are the steps:

  • Modify the server.js file in the .next/standalone directory to handle rewrites.
  • Check for the presence of the x-middleware-rewrite header and process it internally.

Example code:

// .next/standalone/server.js
const { createServer } = require('http');
const { parse } = require('url');
const { join } = require('path');
const { readFile } = require('fs/promises');
const { NextResponse } = require('next/server');

const port = process.env.PORT || 3000;
const hostname = process.env.HOSTNAME || '127.0.0.1';

const server = createServer(async (req, res) => {
  const url = parse(req.url, true);
  const headers = req.headers;

  // Check for x-middleware-rewrite header
  if (headers['x-middleware-rewrite']) {
    const rewriteUrl = new URL(headers['x-middleware-rewrite'], `http://${hostname}:${port}`);
    const rewrittenReq = {
      url: rewriteUrl.href,
      headers: req.headers,
    };

    // Process the rewritten request internally
    const rewrittenRes = await handleRequest(rewrittenReq);
    res.writeHead(rewrittenRes.status, rewrittenRes.headers);
    res.end(rewrittenRes.body);
  } else {
    // Handle the original request
    const response = await handleRequest(req);
    res.writeHead(response.status, response.headers);
    res.end(response.body);
  }
});

async function handleRequest(req) {
  // Your existing request handling logic here
  // For example:
  const filePath = join(__dirname, 'static', req.url);
  const fileContent = await readFile(filePath);
  return new NextResponse(fileContent, {
    status: 200,
    headers: {
      'Content-Type': 'text/html',
    },
  });
}

server.listen(port, hostname, () => {
  console.log(`Server listening on http://${hostname}:${port}`);
});

Verification

To verify that the fix worked, run the standalone server and test the rewrite functionality using curl or a web browser. The server should now process the x-middleware-rewrite header internally and return the rewritten page content with a 200 status code.

Example verification command:

curl -s -D - http://localhost:3000/ | head -3
# HTTP/1.1 200 OK — page content served correctly

Extra Tips

  • Make sure to update the server.js file in the .next/standalone directory to reflect the changes.
  • If you're using a custom middleware, ensure that it's correctly handling

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING