0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-23 21:53:55 -05:00

feat(vercel): skew protection (#10761)

* feat(vercel): skew protection

* feat(vercel): skew protection
This commit is contained in:
Emanuele Stoppa 2024-05-08 15:05:03 +01:00 committed by GitHub
parent a020d0028d
commit f0acd30a12
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 22 additions and 75 deletions

View file

@ -0,0 +1,5 @@
---
"@astrojs/vercel": minor
---
Implements the vercel skew protection

View file

@ -72,16 +72,18 @@ function getAdapter({
edgeMiddleware,
functionPerRoute,
middlewareSecret,
skewProtection,
}: {
edgeMiddleware: boolean;
functionPerRoute: boolean;
middlewareSecret: string;
skewProtection: boolean;
}): AstroAdapter {
return {
name: PACKAGE_NAME,
serverEntrypoint: `${PACKAGE_NAME}/entrypoint`,
exports: ['default'],
args: { middlewareSecret },
args: { middlewareSecret, skewProtection },
adapterFeatures: {
edgeMiddleware,
functionPerRoute,
@ -139,6 +141,10 @@ export interface VercelServerlessConfig {
/** Whether to cache on-demand rendered pages in the same way as static files. */
isr?: boolean | VercelISRConfig;
/**
* It enables Vercel skew protection: https://vercel.com/docs/deployments/skew-protection
*/
skewProtection?: boolean;
}
interface VercelISRConfig {
@ -180,6 +186,7 @@ export default function vercelServerless({
edgeMiddleware = false,
maxDuration,
isr = false,
skewProtection = false,
}: VercelServerlessConfig = {}): AstroIntegration {
if (maxDuration) {
if (typeof maxDuration !== 'number') {
@ -277,7 +284,9 @@ export default function vercelServerless({
);
}
setAdapter(getAdapter({ functionPerRoute, edgeMiddleware, middlewareSecret }));
setAdapter(
getAdapter({ functionPerRoute, edgeMiddleware, middlewareSecret, skewProtection })
);
_config = config;
_buildTempFolder = config.build.server;

View file

@ -12,7 +12,7 @@ applyPolyfills();
export const createExports = (
manifest: SSRManifest,
{ middlewareSecret }: { middlewareSecret: string }
{ middlewareSecret, skewProtection }: { middlewareSecret: string; skewProtection: boolean }
) => {
const app = new NodeApp(manifest);
const handler = async (req: IncomingMessage, res: ServerResponse) => {
@ -38,6 +38,11 @@ export const createExports = (
// hide the secret from the rest of user code
delete req.headers[ASTRO_MIDDLEWARE_SECRET_HEADER];
// https://vercel.com/docs/deployments/skew-protection#supported-frameworks
if (skewProtection && process.env.VERCEL_SKEW_PROTECTION_ENABLED === '1') {
req.headers['x-deployment-id'] = process.env.VERCEL_DEPLOYMENT_ID;
}
const webResponse = await app.render(req, { addCookieHeader: true, clientAddress, locals });
await NodeApp.writeResponse(webResponse, res);
};

View file

@ -1,72 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Middleware with handler file 1`] = `
"// test/fixtures/middleware-with-edge-file/src/vercel-edge-middleware.js
function vercel_edge_middleware_default({ request, context }) {
return {
title: \\"Hello world\\"
};
}
// test/fixtures/middleware-with-edge-file/dist/middleware2.mjs
var onRequest = async (context, next) => {
const response = await next();
return response;
};
// <stdin>
import { createContext, trySerializeLocals } from \\"astro/middleware\\";
async function middleware(request, context) {
const url = new URL(request.url);
const ctx = createContext({
request,
params: {}
});
ctx.locals = vercel_edge_middleware_default({ request, context });
const next = async () => {
const response = await fetch(url, {
headers: {
\\"x-astro-locals\\": trySerializeLocals(ctx.locals)
}
});
return response;
};
return onRequest(ctx, next);
}
export {
middleware as default
};
"
`;
exports[`Middleware without handler file 1`] = `
"// test/fixtures/middleware-without-edge-file/dist/middleware2.mjs
var onRequest = async (context, next) => {
const response = await next();
return response;
};
// <stdin>
import { createContext, trySerializeLocals } from \\"astro/middleware\\";
async function middleware(request, context) {
const url = new URL(request.url);
const ctx = createContext({
request,
params: {}
});
ctx.locals = {};
const next = async () => {
const response = await fetch(url, {
headers: {
\\"x-astro-locals\\": trySerializeLocals(ctx.locals)
}
});
return response;
};
return onRequest(ctx, next);
}
export {
middleware as default
};
"
`;