mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
fix: normalize loopback only in hostname (#90158)
`NextURL` intentionally canonicalizes loopback hosts (127.x.x.x, [::1], localhost) to localhost so that internal URL handling is consistent across equivalent local origins. However, we were applying a regex replacement to the entire URL before parsing, which unintentionally rewrote loopback strings inside query parameter values, eg `?redirect_uri=http%3A%2F%2F127.0.0.1...`. This is unexpected for anyone that is explicitly passing through different loopback values. This fixes it by first parsing the URL with `new URL()`, and then only apply the replacement logic to `parsed.hostname` when it is a loopback host. This leaves search unchanged. Fixes NEXT-4864
This commit is contained in:
@@ -20,13 +20,14 @@ interface Options {
|
||||
}
|
||||
|
||||
const REGEX_LOCALHOST_HOSTNAME =
|
||||
/(?!^https?:\/\/)(127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|\[::1\]|localhost)/
|
||||
/^(?:127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|\[::1\]|localhost)$/
|
||||
|
||||
function parseURL(url: string | URL, base?: string | URL) {
|
||||
return new URL(
|
||||
String(url).replace(REGEX_LOCALHOST_HOSTNAME, 'localhost'),
|
||||
base && String(base).replace(REGEX_LOCALHOST_HOSTNAME, 'localhost')
|
||||
)
|
||||
const parsed = new URL(String(url), base && String(base))
|
||||
if (REGEX_LOCALHOST_HOSTNAME.test(parsed.hostname)) {
|
||||
parsed.hostname = 'localhost'
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
const Internal = Symbol('NextURLInternal')
|
||||
|
||||
@@ -205,6 +205,19 @@ it('consider 127.0.0.1 and variations as localhost', () => {
|
||||
expect(new NextURL('https://[::1]:3000/hello')).toStrictEqual(httpsUrl)
|
||||
})
|
||||
|
||||
it('preserves loopback hostnames inside encoded query parameter values', () => {
|
||||
const url = new NextURL(
|
||||
'https://example.com/api/echo?redirect_uri=http%3A%2F%2F127.0.0.1%3A12345%2Ftest'
|
||||
)
|
||||
|
||||
expect(url.searchParams.get('redirect_uri')).toEqual(
|
||||
'http://127.0.0.1:12345/test'
|
||||
)
|
||||
expect(url.href).toEqual(
|
||||
'https://example.com/api/echo?redirect_uri=http%3A%2F%2F127.0.0.1%3A12345%2Ftest'
|
||||
)
|
||||
})
|
||||
|
||||
it('allows to change the port', () => {
|
||||
const url = new NextURL('https://localhost:3000/foo')
|
||||
url.port = '3001'
|
||||
|
||||
Reference in New Issue
Block a user