Accept: text/markdown header. For an index of Next.js documentation, see /docs/llms.txt.skipProxyUrlNormalize
Enabling skipProxyUrlNormalize lets Proxy see the original request instead of Next.js's normalized version. This includes internal URLs, query parameters, and headers used during client-side navigation.
Most projects don't need this option. It is one of the advanced Proxy flags, meant for specific routing cases and debugging.
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
skipProxyUrlNormalize: true,
}
export default nextConfigReference
During client-side navigation, Next.js uses an internal request rather than requesting the destination URL as a full document load. By default, Next.js normalizes that request before it reaches Proxy, so Proxy sees the same destination URL for both client-side navigation and a full page load.
Next.js also normalizes what Proxy returns, so any URL you rewrite or redirect to is rewritten to match.
With skipProxyUrlNormalize: true, neither normalization runs. Proxy receives the request as sent, and the destinations it rewrites or redirects to are sent as written:
| Default | With skipProxyUrlNormalize: true |
|---|---|
request.nextUrl resolves the internal data URL back to the route path and extracts the locale | Holds the requested pathname as sent |
request.url is the normalized URL | Is the original request URL |
The internal _rsc query parameter is stripped | Preserved |
Next.js internal navigation headers (rsc, next-router-state-tree, next-router-prefetch, next-router-segment-prefetch, next-hmr-refresh) are removed from request.headers | Preserved |
NextResponse.rewrite() destinations are re-serialized with the build ID | Sent as written |
NextResponse.redirect() Location is rewritten to a relative URL | Sent as written, trailing slash preserved |
With trailingSlash: true, a trailing slash is appended before Proxy runs | Pathname passed through unchanged |
Deprecated alias
The former name of this option is skipMiddlewareUrlNormalize, from when Proxy was called Middleware. It still works and logs a deprecation warning. Setting both at once throws:
Config options `skipProxyUrlNormalize` and `skipMiddlewareUrlNormalize` cannot be set at the same time. Please use `skipProxyUrlNormalize` instead.The version 16 codemod renames it for you.
Good to know
- Avoid using the internal navigation headers to return different content for client-side navigation and full page loads.
- You do not need this option to limit which routes Proxy runs on. The
matcherconfig still matches the destination URL either way. - Only the request and response Proxy sees change. Filesystem routing,
redirects, andrewritesfromnext.config.jsbehave the same.
Examples
Reading the URL as the client sent it
During client-side navigation, Next.js adds an _rsc query parameter and its internal navigation headers to the request. With the option enabled, Proxy can read both.
import type { NextRequest } from 'next/server'
export default function proxy(request: NextRequest) {
console.log(request.nextUrl.searchParams.get('_rsc'))
// Enabled: the value Next.js added to the request
// Disabled: null
console.log(request.headers.get('rsc'))
// Enabled: '1' during client-side navigation
// Disabled: null
}Version History
| Version | Changes |
|---|---|
v16.0.0 | Renamed from skipMiddlewareUrlNormalize to skipProxyUrlNormalize. |
v13.1.0 | skipMiddlewareUrlNormalize added. |
Was this helpful?