fix: handle multiple x-forwarded-proto headers (#58824)

### What?
This PR changes how protocol is determined.
A change was recently made (in [PR
57815](1caa58087a (diff-c49c4767e6ed8627e6e1b8f96b141ee13246153f5e9142e1da03450c8e81e96fR1744)))
that did not take into account cases where there are multiple
`x-forwarded-proto` headers. In such cases, the protocol becomes e.g
"https, https".

### Why?
An error will occur in parseUrl on line 1616, since its not a valid url
(e.g. `https, https://localhost:3000`).

### How?
Reverted part of the changes in [PR
57815](https://github.com/vercel/next.js/pull/57815).

Fixes #58764 and fixes #59031

Closes NEXT-2437

---------

Co-authored-by: Balázs Orbán <info@balazsorban.com>
This commit is contained in:
Jonas-PFX 2024-02-14 14:47:26 +01:00 committed by GitHub
parent 45b18bb77e
commit 7744cc91be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 15 additions and 2 deletions

View file

@ -136,7 +136,7 @@ export function getResolveRoutes(
// TODO: inherit this from higher up // TODO: inherit this from higher up
const protocol = const protocol =
(req?.socket as TLSSocket)?.encrypted || (req?.socket as TLSSocket)?.encrypted ||
req.headers['x-forwarded-proto'] === 'https' req.headers['x-forwarded-proto']?.includes('https')
? 'https' ? 'https'
: 'http' : 'http'

View file

@ -1785,7 +1785,9 @@ export default class NextNodeServer extends BaseServer {
isUpgradeReq?: boolean isUpgradeReq?: boolean
) { ) {
// Injected in base-server.ts // Injected in base-server.ts
const protocol = req.headers['x-forwarded-proto'] as 'https' | 'http' const protocol = req.headers['x-forwarded-proto']?.includes('https')
? 'https'
: 'http'
// When there are hostname and port we build an absolute URL // When there are hostname and port we build an absolute URL
const initUrl = const initUrl =

View file

@ -63,5 +63,16 @@ createNextDescribe('x-forwarded-headers', { files: __dirname }, ({ next }) => {
expect(headers['middleware-x-forwarded-port']).toBe(reqHeaders.port) expect(headers['middleware-x-forwarded-port']).toBe(reqHeaders.port)
expect(headers['middleware-x-forwarded-proto']).toBe(reqHeaders.proto) expect(headers['middleware-x-forwarded-proto']).toBe(reqHeaders.proto)
}) })
it('should work with multiple x-forwarded-* headers', async () => {
const res = await next.fetch('/', {
headers: { 'x-forwarded-proto': 'https, https' },
})
expect(res.status).toBe(200)
const headers = await res.json()
expect(headers['x-forwarded-proto']).toBe('https, https')
})
}) })
}) })