mirror of
https://github.com/vercel/flags.git
synced 2026-09-19 03:49:23 +08:00
701f3c2bf2
* use `$env/dynamic/private` from SvelteKit for convenience: people don't have to pass FLAGS_SECRET manually anymore then * allow flag to be called outside of the lifecycle of the handle hook, with a request object being the key for deduplication etc * add support for identifiers * fix types * new function for managing precomputed flags * align with next.js API instead * update example app * lockfile * test * fix example * restructure examples app * make it two flags to show power of precompute + code * add manual approach * lets see if preview deployment is picked up * change crypto usage to be usable in middleware * make sveltekit flags pkg usable within edge middleware * use ISR * changeset * enhance error message * use static env instead of dynamic env * bump kit * use vercel adapter * make sure Vite tooling is used for sveltekit entry point --------- Co-authored-by: Dominik Ferber <dominik.ferber@gmail.com>
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
import { rewrite } from '@vercel/edge';
|
|
import { parse } from 'cookie';
|
|
import { normalizeUrl } from '@sveltejs/kit';
|
|
import { computeInternalRoute, createVisitorId } from './src/lib/precomputed-flags';
|
|
import { marketingABTestManualApproach } from './src/lib/flags';
|
|
|
|
export const config = {
|
|
// Either run middleware on all but the internal asset paths ...
|
|
// matcher: '/((?!_app/|favicon.ico|favicon.png).*)'
|
|
// ... or only run it where you actually need it (more performant).
|
|
matcher: [
|
|
'/examples/marketing-pages-manual-approach',
|
|
'/examples/marketing-pages'
|
|
// add more paths here if you want to run A/B tests on other pages, e.g.
|
|
// '/something-else'
|
|
]
|
|
};
|
|
|
|
export default async function middleware(request: Request) {
|
|
const { url, denormalize } = normalizeUrl(request.url);
|
|
|
|
if (url.pathname === '/examples/marketing-pages-manual-approach') {
|
|
// Retrieve cookies which contain the feature flags.
|
|
let flag = parse(request.headers.get('cookie') ?? '').marketingManual || '';
|
|
|
|
if (!flag) {
|
|
flag = String(Math.random() < 0.5);
|
|
request.headers.set('x-marketingManual', flag); // cookie is not available on the initial request
|
|
}
|
|
|
|
return rewrite(
|
|
// Get destination URL based on the feature flag
|
|
denormalize(
|
|
(await marketingABTestManualApproach(request))
|
|
? '/examples/marketing-pages-variant-a'
|
|
: '/examples/marketing-pages-variant-b'
|
|
),
|
|
{
|
|
headers: {
|
|
'Set-Cookie': `marketingManual=${flag}; Path=/`
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
if (url.pathname === '/examples/marketing-pages') {
|
|
// Retrieve cookies which contain the feature flags.
|
|
let visitorId = parse(request.headers.get('cookie') ?? '').visitorId || '';
|
|
|
|
if (!visitorId) {
|
|
visitorId = createVisitorId();
|
|
request.headers.set('x-visitorId', visitorId); // cookie is not available on the initial request
|
|
}
|
|
|
|
return rewrite(
|
|
// Get destination URL based on the feature flag
|
|
denormalize(await computeInternalRoute(url.pathname, request)),
|
|
{
|
|
headers: {
|
|
'Set-Cookie': `visitorId=${visitorId}; Path=/`
|
|
}
|
|
}
|
|
);
|
|
}
|
|
}
|