Skip to content

Commit

Permalink
fix(@angular/ssr): include Content-Language header when locale is set
Browse files Browse the repository at this point in the history
The server now includes the `Content-Language` HTTP header in responses whenever a locale is explicitly set.

(cherry picked from commit d7214e9)
  • Loading branch information
alan-agius4 committed Dec 7, 2024
1 parent 9ae8351 commit b3c6c7e
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 11 deletions.
24 changes: 15 additions & 9 deletions packages/angular/ssr/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,16 @@ export class AngularServerApp {
}

const assetPath = this.buildServerAssetPathFromRequest(request);
if (!this.assets.hasServerAsset(assetPath)) {
const {
manifest: { locale },
assets,
} = this;

if (!assets.hasServerAsset(assetPath)) {
return null;
}

const { text, hash, size } = this.assets.getServerAsset(assetPath);
const { text, hash, size } = assets.getServerAsset(assetPath);
const etag = `"${hash}"`;

return request.headers.get('if-none-match') === etag
Expand All @@ -224,6 +229,7 @@ export class AngularServerApp {
'Content-Length': size.toString(),
'ETag': etag,
'Content-Type': 'text/html;charset=UTF-8',
...(locale !== undefined ? { 'Content-Language': locale } : {}),
...headers,
},
});
Expand Down Expand Up @@ -254,11 +260,17 @@ export class AngularServerApp {
const url = new URL(request.url);
const platformProviders: StaticProvider[] = [];

const {
manifest: { bootstrap, inlineCriticalCss, locale },
assets,
} = this;

// Initialize the response with status and headers if available.
const responseInit = {
status,
headers: new Headers({
'Content-Type': 'text/html;charset=UTF-8',
...(locale !== undefined ? { 'Content-Language': locale } : {}),
...headers,
}),
};
Expand All @@ -281,18 +293,12 @@ export class AngularServerApp {
);
} else if (renderMode === RenderMode.Client) {
// Serve the client-side rendered version if the route is configured for CSR.
let html = await this.assets.getServerAsset('index.csr.html').text();
let html = await assets.getServerAsset('index.csr.html').text();
html = await this.runTransformsOnHtml(html, url);

return new Response(html, responseInit);
}

const {
manifest: { bootstrap, inlineCriticalCss, locale },
hooks,
assets,
} = this;

if (locale !== undefined) {
platformProviders.push({
provide: LOCALE_ID,
Expand Down
3 changes: 3 additions & 0 deletions packages/angular/ssr/test/app-engine_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ function createEntryPoint(locale: string) {
`,
},
},
locale,
);

return {
Expand Down Expand Up @@ -110,12 +111,14 @@ describe('AngularAppEngine', () => {
const request = new Request('https://example.com/it/ssr/index.html');
const response = await appEngine.handle(request);
expect(await response?.text()).toContain('SSR works IT');
expect(response?.headers?.get('Content-Language')).toBe('it');
});

it('should return a serve prerendered page with correct locale', async () => {
const request = new Request('https://example.com/it/ssg');
const response = await appEngine.handle(request);
expect(await response?.text()).toContain('SSG works IT');
expect(response?.headers?.get('Content-Language')).toBe('it');
});

it('should correctly serve the prerendered content when the URL ends with "index.html" with correct locale', async () => {
Expand Down
9 changes: 7 additions & 2 deletions packages/angular/ssr/test/testing-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ import { ServerRoute, provideServerRoutesConfig } from '../src/routes/route-conf
* Angular components and providers for testing purposes.
*
* @param routes - An array of route definitions to be used by the Angular Router.
* @param serverRoutes - An array of ServerRoute definitions to be used for server-side rendering.
* @param [baseHref='/'] - An optional base href to be used in the HTML template.
* @param serverRoutes - An array of server route definitions for server-side rendering.
* @param [baseHref='/'] - An optional base href for the HTML template (default is `/`).
* @param additionalServerAssets - A record of additional server assets to include,
* where the keys are asset paths and the values are asset details.
* @param locale - An optional locale to configure for the application during testing.
*/
export function setAngularAppTestingManifest(
routes: Routes,
serverRoutes: ServerRoute[],
baseHref = '/',
additionalServerAssets: Record<string, ServerAsset> = {},
locale?: string,
): void {
destroyAngularServerApp();

Expand All @@ -43,6 +47,7 @@ export function setAngularAppTestingManifest(
setAngularAppManifest({
inlineCriticalCss: false,
baseHref,
locale,
assets: {
...additionalServerAssets,
'index.server.html': {
Expand Down

0 comments on commit b3c6c7e

Please sign in to comment.