Skip to content

Commit 39529bc

Browse files
authored
Merge pull request #67599 from code-dot-org/stephen/home-redirect
feat(marketing): only redirect home page if code.org
2 parents b972f36 + cc512b2 commit 39529bc

File tree

2 files changed

+81
-43
lines changed

2 files changed

+81
-43
lines changed

frontend/apps/marketing/src/middleware/__tests__/withLocale.test.ts

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import {NextRequest, NextFetchEvent, NextResponse} from 'next/server';
22

33
import {STALE_WHILE_REVALIDATE_ONE_HOUR} from '@/cache/constants';
4-
import {SUPPORTED_LOCALE_CODES, SUPPORTED_LOCALES_SET} from '@/config/locale';
4+
import {
5+
SUPPORTED_LOCALE_CODES,
6+
SUPPORTED_LOCALES_SET,
7+
SupportedLocale,
8+
} from '@/config/locale';
59
import {getStage} from '@/config/stage';
610
import {getContentfulSlug} from '@/contentful/slug/getContentfulSlug';
711

@@ -40,15 +44,19 @@ describe('withLocale middleware', () => {
4044
response: {cookies: {set: jest.fn()}},
4145
} as unknown as NextRequest;
4246

43-
SUPPORTED_LOCALES_SET.add('zh-TW');
47+
SUPPORTED_LOCALES_SET.add('zh-TW' as SupportedLocale);
4448
await withLocale(next)(request, mockEvent);
4549

4650
expect(next).toHaveBeenCalledWith(request, mockEvent);
4751
expect(getContentfulSlug).not.toHaveBeenCalled();
48-
expect(cookieMock.set).toHaveBeenCalledWith('language_', 'zh-TW', {
49-
domain: undefined,
50-
path: '/',
51-
});
52+
expect(cookieMock.set).toHaveBeenCalledWith(
53+
'language_',
54+
'zh-TW' as SupportedLocale,
55+
{
56+
domain: undefined,
57+
path: '/',
58+
},
59+
);
5260
});
5361

5462
it('should not redirect if the path contains a supported locale - development', async () => {
@@ -60,26 +68,30 @@ describe('withLocale middleware', () => {
6068
} as unknown as NextRequest;
6169
(getStage as jest.Mock).mockReturnValue('production');
6270

63-
SUPPORTED_LOCALES_SET.add('zh-TW');
71+
SUPPORTED_LOCALES_SET.add('zh-TW' as SupportedLocale);
6472
await withLocale(next)(request, mockEvent);
6573

6674
expect(next).toHaveBeenCalledWith(request, mockEvent);
6775
expect(getContentfulSlug).not.toHaveBeenCalled();
68-
expect(cookieMock.set).toHaveBeenCalledWith('language_', 'zh-TW', {
69-
domain: '.code.org',
70-
path: '/',
71-
});
76+
expect(cookieMock.set).toHaveBeenCalledWith(
77+
'language_',
78+
'zh-TW' as SupportedLocale,
79+
{
80+
domain: '.code.org',
81+
path: '/',
82+
},
83+
);
7284
});
7385

7486
it('should redirect to the locale path if no locale is present in the path for cookies', async () => {
7587
const request = {
7688
url: 'https://test.code.org',
7789
nextUrl: {pathname: '/home', url: 'https://test.code.org/home'},
78-
cookies: {get: jest.fn(() => ({value: 'zh-TW'}))},
90+
cookies: {get: jest.fn(() => ({value: 'zh-TW' as SupportedLocale}))},
7991
headers: {get: jest.fn()},
8092
} as unknown as NextRequest;
8193

82-
SUPPORTED_LOCALES_SET.add('zh-TW');
94+
SUPPORTED_LOCALES_SET.add('zh-TW' as SupportedLocale);
8395
(getContentfulSlug as jest.Mock).mockReturnValue('home');
8496

8597
const response = await withLocale(next)(request, mockEvent);
@@ -103,7 +115,7 @@ describe('withLocale middleware', () => {
103115
},
104116
} as unknown as NextRequest;
105117

106-
SUPPORTED_LOCALE_CODES.push('zh-TW');
118+
SUPPORTED_LOCALE_CODES.push('zh-TW' as SupportedLocale);
107119
(getContentfulSlug as jest.Mock).mockReturnValue('home');
108120

109121
const response = await withLocale(next)(request, mockEvent);
@@ -127,7 +139,7 @@ describe('withLocale middleware', () => {
127139
},
128140
} as unknown as NextRequest;
129141

130-
SUPPORTED_LOCALE_CODES.push('en-US');
142+
SUPPORTED_LOCALE_CODES.push('en-US' as SupportedLocale);
131143
(getContentfulSlug as jest.Mock).mockReturnValue('home');
132144

133145
const response = await withLocale(next)(request, mockEvent);
@@ -182,11 +194,11 @@ describe('withLocale middleware', () => {
182194
pathname: '/engineering/all-the-things',
183195
url: 'https://test.code.org/engineering/all-the-things',
184196
},
185-
cookies: {get: jest.fn(() => ({value: 'zh-TW'}))},
197+
cookies: {get: jest.fn(() => ({value: 'zh-TW' as SupportedLocale}))},
186198
headers: {get: jest.fn()},
187199
} as unknown as NextRequest;
188200

189-
SUPPORTED_LOCALES_SET.add('zh-TW');
201+
SUPPORTED_LOCALES_SET.add('zh-TW' as SupportedLocale);
190202
(getContentfulSlug as jest.Mock).mockReturnValue(
191203
'engineering/all-the-things',
192204
);
@@ -198,4 +210,23 @@ describe('withLocale middleware', () => {
198210
'https://test.code.org/zh-TW/engineering/all-the-things',
199211
);
200212
});
213+
214+
it('should not set language_ cookie or redirect to studio base url when brand is not CODE_DOT_ORG', async () => {
215+
const request = {
216+
nextUrl: {pathname: '/zh-TW/home'},
217+
cookies: {get: jest.fn()},
218+
headers: {get: jest.fn().mockReturnValue('csforall.org')},
219+
response: {cookies: {set: jest.fn()}},
220+
url: 'https://not-code.org/zh-TW/home',
221+
} as unknown as NextRequest;
222+
223+
SUPPORTED_LOCALES_SET.add('zh-TW' as SupportedLocale);
224+
await withLocale(next)(request, mockEvent);
225+
226+
expect(cookieMock.set).not.toHaveBeenCalledWith(
227+
'language_',
228+
expect.anything(),
229+
expect.anything(),
230+
);
231+
});
201232
});

frontend/apps/marketing/src/middleware/withLocale.ts

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Negotiator from 'negotiator';
22
import {NextFetchEvent, NextRequest} from 'next/server';
33

4+
import {Brand, getBrandFromHostname} from '@/config/brand';
45
import {
56
getLocalizeJsLocaleFromDashboardLocale,
67
getDashboardLocale,
@@ -52,33 +53,37 @@ export const withLocale: MiddlewareFactory = next => {
5253

5354
const maybeLocale = pathParts[0] as SupportedLocale;
5455
const stage = getStage();
55-
56-
if (SUPPORTED_LOCALES_SET.has(maybeLocale)) {
57-
// If the first part of the path is a supported locale or there are no subpaths, we don't need to redirect
58-
const response = await next(request, event);
59-
60-
response.cookies.set('language_', getDashboardLocale(maybeLocale), {
61-
path: '/',
62-
domain: stage === 'production' ? '.code.org' : undefined,
63-
});
64-
65-
return response;
66-
}
56+
const hostname = request.headers.get('host');
57+
const brand = getBrandFromHostname(hostname);
6758

6859
// If pathParts is empty, then it is a request to / which should resolve to the / slug
6960
// It is an empty string here because when a call is made to Contentful, `/` is automatically prepended
7061
const isRootRoute = pathParts.length === 0;
7162

72-
if (isRootRoute) {
73-
// If the _user_type cookie is set, then Dashboard successfully logged in the user which is an early indicator
74-
// that the user is logged in right now. Therefore, send the user to Code Studio
75-
// See: https://github.com/code-dot-org/code-dot-org/blob/3fad8bce055846378ae3da343da93a32acd4df8c/dashboard/config/initializers/devise.rb#L331
76-
const userTypeCookie = request.cookies.get(
77-
getCookieNameByStage('_user_type', stage),
78-
);
63+
if (brand === Brand.CODE_DOT_ORG) {
64+
if (SUPPORTED_LOCALES_SET.has(maybeLocale)) {
65+
// If the first part of the path is a supported locale or there are no subpaths, we don't need to redirect
66+
const response = await next(request, event);
7967

80-
if (userTypeCookie?.value) {
81-
return getCachedRedirectResponse(getStudioBaseUrl());
68+
response.cookies.set('language_', getDashboardLocale(maybeLocale), {
69+
path: '/',
70+
domain: stage === 'production' ? '.code.org' : undefined,
71+
});
72+
73+
return response;
74+
}
75+
76+
if (isRootRoute) {
77+
// If the _user_type cookie is set, then Dashboard successfully logged in the user which is an early indicator
78+
// that the user is logged in right now. Therefore, send the user to Code Studio
79+
// See: https://github.com/code-dot-org/code-dot-org/blob/3fad8bce055846378ae3da343da93a32acd4df8c/dashboard/config/initializers/devise.rb#L331
80+
const userTypeCookie = request.cookies.get(
81+
getCookieNameByStage('_user_type', stage),
82+
);
83+
84+
if (userTypeCookie?.value) {
85+
return getCachedRedirectResponse(getStudioBaseUrl());
86+
}
8287
}
8388
}
8489

@@ -99,11 +104,13 @@ export const withLocale: MiddlewareFactory = next => {
99104
const redirectUrl = new URL(localizedPath, request.url);
100105
const response = getCachedRedirectResponse(redirectUrl);
101106

102-
// Set the language cookie if discovered via Accept-Language header
103-
response.cookies.set('language_', getDashboardLocale(locale), {
104-
path: '/',
105-
domain: getStage() === 'production' ? '.code.org' : undefined,
106-
});
107+
if (brand === Brand.CODE_DOT_ORG) {
108+
// Set the language cookie if discovered via Accept-Language header
109+
response.cookies.set('language_', getDashboardLocale(locale), {
110+
path: '/',
111+
domain: getStage() === 'production' ? '.code.org' : undefined,
112+
});
113+
}
107114

108115
return response;
109116
};

0 commit comments

Comments
 (0)