diff --git a/apps/dashboard/src/middleware.test.ts b/apps/dashboard/src/middleware.test.ts index e8e04d9..cc9960e 100644 --- a/apps/dashboard/src/middleware.test.ts +++ b/apps/dashboard/src/middleware.test.ts @@ -77,7 +77,7 @@ describe('dashboard middleware', () => { const response = middleware(request('http://dashboard:3001/dashboard/team') as never) - expect(response).toEqual({ kind: 'redirect', url: 'https://rentaldrivego.example:3001/dashboard/sign-in?redirect=%2Fdashboard%2Fteam' }) + expect(response).toEqual({ kind: 'redirect', url: 'https://rentaldrivego.example/dashboard/sign-in?redirect=%2Fdashboard%2Fteam' }) }) it('uses trusted forwarded host/proto when building the dashboard sign-in redirect', async () => { @@ -90,7 +90,7 @@ describe('dashboard middleware', () => { }, }) as never) - expect(response).toEqual({ kind: 'redirect', url: 'https://workspace.customer.example:3001/dashboard/sign-in?redirect=%2Fdashboard%2Fbilling' }) + expect(response).toEqual({ kind: 'redirect', url: 'https://workspace.customer.example/dashboard/sign-in?redirect=%2Fdashboard%2Fbilling' }) }) it('ignores internal forwarded hosts when building the dashboard sign-in redirect', async () => { @@ -103,7 +103,7 @@ describe('dashboard middleware', () => { }, }) as never) - expect(response).toEqual({ kind: 'redirect', url: 'https://market.example.com:3001/dashboard/sign-in?redirect=%2Fdashboard%2Ffleet' }) + expect(response).toEqual({ kind: 'redirect', url: 'https://market.example.com/dashboard/sign-in?redirect=%2Fdashboard%2Ffleet' }) }) it('redirects signed-in users away from the sign-in page', async () => { diff --git a/apps/dashboard/src/middleware.ts b/apps/dashboard/src/middleware.ts index 5a72977..5f28032 100644 --- a/apps/dashboard/src/middleware.ts +++ b/apps/dashboard/src/middleware.ts @@ -38,16 +38,27 @@ function resolveProxyUrl(req: NextRequest, pathname: string): URL { if (forwardedHost && !isInternalHost(forwardedHost)) { url.host = forwardedHost url.protocol = (forwardedProto ?? 'http') + ':' + if (!hasExplicitPort(forwardedHost) || isInternalAppPort(url.port)) url.port = '' } else if (!isInternalHost(req.nextUrl.host)) { url.host = req.nextUrl.host url.protocol = req.nextUrl.protocol + if (!hasExplicitPort(req.nextUrl.host) || isInternalAppPort(url.port)) url.port = '' } else { url.host = storefrontOrigin.host url.protocol = storefrontOrigin.protocol + if (!hasExplicitPort(storefrontOrigin.host) || isInternalAppPort(url.port)) url.port = '' } return url } +function hasExplicitPort(host: string): boolean { + return /^[^:]+:\d+$/.test(host) +} + +function isInternalAppPort(port: string): boolean { + return ['3000', '3001', '3002', '3004', '4000'].includes(port) +} + function isInternalHost(host: string | null): boolean { if (!host) return false const hostname = host.split(':')[0]?.toLowerCase()