Skip to content

Commit

Permalink
fix: Use correct port for alternate links when running behind a proxy (
Browse files Browse the repository at this point in the history
…#514 by @iza-w)



Co-authored-by: Jan Amann <jan@amann.me>
  • Loading branch information
iza-w and amannn committed Sep 21, 2023
1 parent c14f50c commit 747ad5b
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 22 deletions.
1 change: 1 addition & 0 deletions packages/next-intl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"devDependencies": {
"@edge-runtime/vm": "^3.1.3",
"@size-limit/preset-big-lib": "^8.2.6",
"@testing-library/react": "^13.0.0",
"@types/negotiator": "^0.6.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import {getHost, isLocaleSupportedOnDomain} from './utils';

function getUnprefixedUrl(config: MiddlewareConfig, request: NextRequest) {
const url = new URL(request.url);
url.host = getHost(request.headers) ?? url.host;
const host = getHost(request.headers);
if (host) {
url.port = '';
url.host = host;
}
url.protocol = request.headers.get('x-forwarded-proto') ?? url.protocol;

if (!url.pathname.endsWith('/')) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// @vitest-environment edge-runtime

import {NextRequest} from 'next/server';
import {it, expect} from 'vitest';
import {MiddlewareConfigWithDefaults} from '../../src/middleware/NextIntlMiddlewareConfig';
Expand Down Expand Up @@ -215,3 +217,57 @@ it('uses the external host name from headers instead of the url of the incoming
'<https://example.com/about>; rel="alternate"; hreflang="x-default"'
]);
});

it('keeps the port of an external host if provided', () => {
const config: MiddlewareConfigWithDefaults = {
defaultLocale: 'en',
locales: ['en', 'es'],
alternateLinks: true,
localePrefix: 'as-needed',
localeDetection: true
};

expect(
getAlternateLinksHeaderValue(
config,
new NextRequest('http://127.0.0.1/about', {
headers: {
host: 'example.com:3000',
'x-forwarded-host': 'example.com:3000',
'x-forwarded-proto': 'https'
}
})
).split(', ')
).toEqual([
'<https://example.com:3000/about>; rel="alternate"; hreflang="en"',
'<https://example.com:3000/es/about>; rel="alternate"; hreflang="es"',
'<https://example.com:3000/about>; rel="alternate"; hreflang="x-default"'
]);
});

it('uses the external host name and the port from headers instead of the url with port of the incoming request (relevant when running the app behind a proxy)', () => {
const config: MiddlewareConfigWithDefaults = {
defaultLocale: 'en',
locales: ['en', 'es'],
alternateLinks: true,
localePrefix: 'as-needed',
localeDetection: true
};

expect(
getAlternateLinksHeaderValue(
config,
new NextRequest('http://127.0.0.1:3000/about', {
headers: {
host: 'example.com',
'x-forwarded-host': 'example.com',
'x-forwarded-proto': 'https'
}
})
).split(', ')
).toEqual([
'<https://example.com/about>; rel="alternate"; hreflang="en"',
'<https://example.com/es/about>; rel="alternate"; hreflang="es"',
'<https://example.com/about>; rel="alternate"; hreflang="x-default"'
]);
});
10 changes: 6 additions & 4 deletions packages/next-intl/test/middleware/middleware.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// @vitest-environment edge-runtime

import {RequestCookies} from 'next/dist/compiled/@edge-runtime/cookies';
import {NextRequest, NextResponse} from 'next/server';
import {pathToRegexp} from 'path-to-regexp';
Expand All @@ -6,7 +8,7 @@ import createIntlMiddleware from '../../src/middleware';
import {COOKIE_LOCALE_NAME} from '../../src/shared/constants';

vi.mock('next/server', () => {
type MiddlewareResponseInit = Parameters<(typeof NextResponse)['next']>[0];
type MiddlewareResponseInit = Parameters<typeof NextResponse['next']>[0];

function createResponse(init: MiddlewareResponseInit) {
const response = new Response(null, init);
Expand Down Expand Up @@ -60,9 +62,9 @@ function createMockRequest(
}

const MockedNextResponse = NextResponse as unknown as {
next: Mock<Parameters<(typeof NextResponse)['next']>>;
rewrite: Mock<Parameters<(typeof NextResponse)['rewrite']>>;
redirect: Mock<Parameters<(typeof NextResponse)['redirect']>>;
next: Mock<Parameters<typeof NextResponse['next']>>;
rewrite: Mock<Parameters<typeof NextResponse['rewrite']>>;
redirect: Mock<Parameters<typeof NextResponse['redirect']>>;
};

beforeEach(() => {
Expand Down
46 changes: 29 additions & 17 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 comments on commit 747ad5b

@vercel
Copy link

@vercel vercel bot commented on 747ad5b Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

next-intl-example-next-13 – ./examples/example-next-13

next-intl-example-next-13.vercel.app
next-intl-example-next-13-next-intl.vercel.app
next-intl-example-next-13-git-main-next-intl.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 747ad5b Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

next-intl-docs – ./docs

next-intl-docs-next-intl.vercel.app
next-intl-docs-git-main-next-intl.vercel.app
next-intl-docs.vercel.app

Please sign in to comment.