Files
readest/apps/readest-app/src/middleware.ts
T
2026-05-07 20:11:47 +02:00

63 lines
1.8 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
const allowedOrigins = [
'https://web.readest.com',
'https://tauri.localhost',
'http://tauri.localhost',
'http://localhost:3000',
'http://localhost:3001',
'tauri://localhost',
];
const corsOptions = {
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': '*',
'Access-Control-Max-Age': '86400',
};
export function middleware(request: NextRequest) {
const isApi = request.nextUrl.pathname.startsWith('/api/');
if (isApi) {
const origin = request.headers.get('origin') ?? '';
const isAllowedOrigin = allowedOrigins.includes(origin);
if (request.method === 'OPTIONS') {
const preflightHeaders = new Headers({
...corsOptions,
...(isAllowedOrigin && { 'Access-Control-Allow-Origin': origin }),
});
return new NextResponse(null, {
status: 200,
headers: preflightHeaders,
});
}
const response = NextResponse.next();
if (isAllowedOrigin) {
response.headers.set('Access-Control-Allow-Origin', origin);
}
Object.entries(corsOptions).forEach(([key, value]) => {
response.headers.set(key, value);
});
return response;
}
// Cross-origin isolation enables SharedArrayBuffer, which the Turso WASM
// thread pool requires (initThreadPool hangs without it). Set on every
// document response, not just /api/* — `crossOriginIsolated` is a property
// of the top-level browsing context, determined by the document's headers.
const response = NextResponse.next();
response.headers.set('Cross-Origin-Opener-Policy', 'same-origin');
response.headers.set('Cross-Origin-Embedder-Policy', 'require-corp');
return response;
}
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico|sw.js|manifest.json).*)'],
};