1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
import type { Context } from '@netlify/functions';
import type { SSRManifest } from 'astro';
import { App } from 'astro/app';
import { applyPolyfills } from 'astro/app/node';
applyPolyfills();
// biome-ignore lint/complexity/noBannedTypes: safe to use in this case
export type Args = {};
const clientAddressSymbol = Symbol.for('astro.clientAddress');
export const createExports = (manifest: SSRManifest, _args: Args) => {
const app = new App(manifest);
function createHandler(integrationConfig: { cacheOnDemandPages: boolean, notFoundContent?: string }) {
return async function handler(request: Request, context: Context) {
const routeData = app.match(request);
if (!routeData && typeof integrationConfig.notFoundContent !== 'undefined') {
return new Response(integrationConfig.notFoundContent, { status: 404 });
}
Reflect.set(request, clientAddressSymbol, context.ip);
let locals: Record<string, unknown> = {};
const astroLocalsHeader = request.headers.get('x-astro-locals');
if (astroLocalsHeader) {
locals = JSON.parse(astroLocalsHeader);
}
locals.netlify = { context };
const response = await app.render(request, { routeData, locals });
if (app.setCookieHeaders) {
for (const setCookieHeader of app.setCookieHeaders(response)) {
response.headers.append('Set-Cookie', setCookieHeader);
}
}
if (integrationConfig.cacheOnDemandPages) {
const isCacheableMethod = ['GET', 'HEAD'].includes(request.method);
// any user-provided Cache-Control headers take precedence
const hasCacheControl = [
'Cache-Control',
'CDN-Cache-Control',
'Netlify-CDN-Cache-Control',
].some((header) => response.headers.has(header));
if (isCacheableMethod && !hasCacheControl) {
// caches this page for up to a year
response.headers.append('CDN-Cache-Control', 'public, max-age=31536000, must-revalidate');
}
}
return response;
};
}
return { default: createHandler };
};
|