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:
parent
a020d0028d
commit
f0acd30a12
4 changed files with 22 additions and 75 deletions
5
.changeset/honest-games-bathe.md
Normal file
5
.changeset/honest-games-bathe.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@astrojs/vercel": minor
|
||||
---
|
||||
|
||||
Implements the vercel skew protection
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
"
|
||||
`;
|
Loading…
Reference in a new issue