GuardRateLeaderboard / src /hooks.server.ts
Anton Malykhin
feat: optimize bucket data caching and document refresh behavior
a290b8b
Raw
History Blame Contribute Delete
2.61 kB
import type { Handle } from '@sveltejs/kit';
import { getTextDirection, isLocale } from '$lib/paraglide/runtime';
import { paraglideMiddleware } from '$lib/paraglide/server';
const DATA_CACHE_CONTROL = 'private, max-age=300';
const MIN_GZIP_SIZE_BYTES = 1024;
function isBucketDataRequest(request: Request) {
const segments = new URL(request.url).pathname.split('/').filter(Boolean);
if (segments.at(-1) !== '__data.json') return false;
segments.pop();
if (segments[0] && isLocale(segments[0])) segments.shift();
const route = segments.join('/');
return route === '' || route === 'details' || route === 'tools';
}
function acceptsGzip(request: Request) {
return (request.headers.get('accept-encoding') ?? '').split(',').some((entry) => {
const [encoding, ...parameters] = entry.trim().toLowerCase().split(';');
if (encoding !== 'gzip' && encoding !== '*') return false;
const quality = parameters
.map((parameter) => parameter.trim())
.find((parameter) => parameter.startsWith('q='));
return quality ? Number(quality.slice(2)) > 0 : true;
});
}
function appendVary(headers: Headers, value: string) {
const values = new Set(
(headers.get('vary') ?? '')
.split(',')
.map((item) => item.trim())
.filter(Boolean)
);
values.add(value);
headers.set('vary', [...values].join(', '));
}
function optimizeBucketDataResponse(request: Request, response: Response) {
if (!response.ok || !response.body || !isBucketDataRequest(request)) return response;
const headers = new Headers(response.headers);
headers.set('cache-control', DATA_CACHE_CONTROL);
appendVary(headers, 'Accept-Encoding');
const contentLength = Number(headers.get('content-length') ?? 0);
if (request.method === 'HEAD' || contentLength < MIN_GZIP_SIZE_BYTES || !acceptsGzip(request)) {
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers
});
}
headers.delete('content-length');
headers.set('content-encoding', 'gzip');
return new Response(response.body.pipeThrough(new CompressionStream('gzip')), {
status: response.status,
statusText: response.statusText,
headers
});
}
const handleParaglide: Handle = ({ event, resolve }) =>
paraglideMiddleware(event.request, async ({ request, locale }) => {
event.request = request;
const response = await resolve(event, {
transformPageChunk: ({ html }) =>
html
.replace('%paraglide.lang%', locale)
.replace('%paraglide.dir%', getTextDirection(locale))
});
return optimizeBucketDataResponse(request, response);
});
export const handle: Handle = handleParaglide;