Skip to content

Commit 55e4a3d

Browse files
authoredFeb 11, 2021
Only create locale domain links if on locale domain (#22032)
This updates to only create locale domain links if the current hostname is a locale domain to prevent making links unvisitable in development and preview environments where the configured locale domains don't point to the current build. Closes: #21211 Closes: #22011
1 parent 5febe21 commit 55e4a3d

File tree

7 files changed

+77
-13
lines changed

7 files changed

+77
-13
lines changed
 

‎packages/next/build/webpack/loaders/next-serverless-loader/utils.ts

+1
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ export function getUtils({
349349
if (detectedDomain) {
350350
defaultLocale = detectedDomain.defaultLocale
351351
detectedLocale = defaultLocale
352+
;(req as any).__nextIsLocaleDomain = true
352353
}
353354

354355
// if not domain specific locale use accept-language preferred

‎packages/next/client/link.tsx

+11-6
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,17 @@ function Link(props: React.PropsWithChildren<LinkProps>) {
301301
const curLocale =
302302
typeof locale !== 'undefined' ? locale : router && router.locale
303303

304-
const localeDomain = getDomainLocale(
305-
as,
306-
curLocale,
307-
router && router.locales,
308-
router && router.domainLocales
309-
)
304+
// we only render domain locales if we are currently on a domain locale
305+
// so that locale links are still visitable in development/preview envs
306+
const localeDomain =
307+
router &&
308+
router.isLocaleDomain &&
309+
getDomainLocale(
310+
as,
311+
curLocale,
312+
router && router.locales,
313+
router && router.domainLocales
314+
)
310315

311316
childProps.href =
312317
localeDomain ||

‎packages/next/client/router.ts

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const urlPropertyFields = [
4141
'locales',
4242
'defaultLocale',
4343
'isReady',
44+
'isLocaleDomain',
4445
]
4546
const routerEvents = [
4647
'routeChangeStart',

‎packages/next/next-server/lib/router/router.ts

+8
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ export type BaseRouter = {
348348
locales?: string[]
349349
defaultLocale?: string
350350
domainLocales?: DomainLocales
351+
isLocaleDomain: boolean
351352
}
352353

353354
export type NextRouter = BaseRouter &
@@ -488,6 +489,7 @@ export default class Router implements BaseRouter {
488489
defaultLocale?: string
489490
domainLocales?: DomainLocales
490491
isReady: boolean
492+
isLocaleDomain: boolean
491493

492494
private _idx: number = 0
493495

@@ -579,12 +581,17 @@ export default class Router implements BaseRouter {
579581
self.__NEXT_DATA__.gip ||
580582
(!autoExportDynamic && !self.location.search)
581583
)
584+
this.isLocaleDomain = false
582585

583586
if (process.env.__NEXT_I18N_SUPPORT) {
584587
this.locale = locale
585588
this.locales = locales
586589
this.defaultLocale = defaultLocale
587590
this.domainLocales = domainLocales
591+
this.isLocaleDomain = !!detectDomainLocale(
592+
domainLocales,
593+
self.location.hostname
594+
)
588595
}
589596

590597
if (typeof window !== 'undefined') {
@@ -817,6 +824,7 @@ export default class Router implements BaseRouter {
817824
if (
818825
!didNavigate &&
819826
detectedDomain &&
827+
this.isLocaleDomain &&
820828
self.location.hostname !== detectedDomain.domain
821829
) {
822830
const asNoBasePath = delBasePath(as)

‎packages/next/next-server/server/next-server.ts

+1
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ export default class Server {
443443
if (detectedDomain) {
444444
defaultLocale = detectedDomain.defaultLocale
445445
detectedLocale = defaultLocale
446+
;(req as any).__nextIsLocaleDomain = true
446447
}
447448

448449
// if not domain specific locale use accept-language preferred

‎packages/next/next-server/server/render.tsx

+9-5
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class ServerRouter implements NextRouter {
8080
locales?: string[]
8181
defaultLocale?: string
8282
domainLocales?: DomainLocales
83+
isLocaleDomain: boolean
8384
// TODO: Remove in the next major version, as this would mean the user is adding event listeners in server-side `render` method
8485
static events: MittEmitter = mitt()
8586

@@ -90,10 +91,11 @@ class ServerRouter implements NextRouter {
9091
{ isFallback }: { isFallback: boolean },
9192
isReady: boolean,
9293
basePath: string,
93-
locale?: string,
94-
locales?: string[],
95-
defaultLocale?: string,
96-
domainLocales?: DomainLocales
94+
locale: string | undefined,
95+
locales: string[] | undefined,
96+
defaultLocale: string | undefined,
97+
domainLocales: DomainLocales | undefined,
98+
isLocaleDomain: boolean
9799
) {
98100
this.route = pathname.replace(/\/$/, '') || '/'
99101
this.pathname = pathname
@@ -106,6 +108,7 @@ class ServerRouter implements NextRouter {
106108
this.defaultLocale = defaultLocale
107109
this.isReady = isReady
108110
this.domainLocales = domainLocales
111+
this.isLocaleDomain = isLocaleDomain
109112
}
110113

111114
push(): any {
@@ -550,7 +553,8 @@ export async function renderToHTML(
550553
renderOpts.locale,
551554
renderOpts.locales,
552555
renderOpts.defaultLocale,
553-
renderOpts.domainLocales
556+
renderOpts.domainLocales,
557+
(req as any).__nextIsLocaleDomain
554558
)
555559
const ctx = {
556560
err,

‎test/integration/i18n-support/test/shared.js

+46-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ export function runTests(ctx) {
6767
})
6868
})
6969

70-
it('should redirect to locale domain correctly client-side', async () => {
70+
// this test can not currently be tested in browser without modifying the
71+
// host resolution since it needs a domain to test locale domains behavior
72+
it.skip('should redirect to locale domain correctly client-side', async () => {
7173
const browser = await webdriver(ctx.appPort, `${ctx.basePath || '/'}`)
7274

7375
await browser.eval(`(function() {
@@ -104,7 +106,9 @@ export function runTests(ctx) {
104106
)
105107
})
106108

107-
it('should render the correct href for locale domain', async () => {
109+
// this test can not currently be tested in browser without modifying the
110+
// host resolution since it needs a domain to test locale domains behavior
111+
it.skip('should render the correct href for locale domain', async () => {
108112
let browser = await webdriver(
109113
ctx.appPort,
110114
`${ctx.basePath || ''}/links?nextLocale=go`
@@ -142,6 +146,46 @@ export function runTests(ctx) {
142146
}
143147
})
144148

149+
it('should render the correct href with locale domains but not on a locale domain', async () => {
150+
let browser = await webdriver(
151+
ctx.appPort,
152+
`${ctx.basePath || ''}/links?nextLocale=go`
153+
)
154+
155+
for (const [element, pathname] of [
156+
['#to-another', '/another'],
157+
['#to-gsp', '/gsp'],
158+
['#to-fallback-first', '/gsp/fallback/first'],
159+
['#to-fallback-hello', '/gsp/fallback/hello'],
160+
['#to-gssp', '/gssp'],
161+
['#to-gssp-slug', '/gssp/first'],
162+
]) {
163+
const href = await browser.elementByCss(element).getAttribute('href')
164+
const { hostname, pathname: hrefPathname } = url.parse(href)
165+
expect(hostname).not.toBe('example.com')
166+
expect(hrefPathname).toBe(`${ctx.basePath || ''}/go${pathname}`)
167+
}
168+
169+
browser = await webdriver(
170+
ctx.appPort,
171+
`${ctx.basePath || ''}/links?nextLocale=go-BE`
172+
)
173+
174+
for (const [element, pathname] of [
175+
['#to-another', '/another'],
176+
['#to-gsp', '/gsp'],
177+
['#to-fallback-first', '/gsp/fallback/first'],
178+
['#to-fallback-hello', '/gsp/fallback/hello'],
179+
['#to-gssp', '/gssp'],
180+
['#to-gssp-slug', '/gssp/first'],
181+
]) {
182+
const href = await browser.elementByCss(element).getAttribute('href')
183+
const { hostname, pathname: hrefPathname } = url.parse(href)
184+
expect(hostname).not.toBe('example.com')
185+
expect(hrefPathname).toBe(`${ctx.basePath || ''}/go-BE${pathname}`)
186+
}
187+
})
188+
145189
it('should navigate through history with query correctly', async () => {
146190
const browser = await webdriver(ctx.appPort, `${ctx.basePath || '/'}`)
147191

0 commit comments

Comments
 (0)
Please sign in to comment.