import type { Core } from '@strapi/strapi'; /** * Origins that are always allowed outside production: the React Router dev * server (Vite) on both hostnames it is commonly reached on. */ const DEV_ORIGINS = [ 'http://localhost:5173', 'http://127.0.0.1:5173', ]; /** * The default Strapi middleware stack, in order, with CORS configured for the * SHARP-ER web app. * * Order matters: `strapi::errors` must wrap everything after it, `strapi::cors` * must run before routing so pre-flight requests are answered, and * `strapi::public` stays last so it only handles what nothing else claimed. */ const config = ({ env }: Core.Config.Shared.ConfigParams): Core.Config.Middlewares => { const isProduction = env('NODE_ENV', 'development') === 'production'; /** * Production origins come from the environment, e.g. * CORS_ORIGINS=https://sharper.ly,https://www.sharper.ly * Outside production the local dev server is allowed as well. */ const configuredOrigins = env.array('CORS_ORIGINS', []) as string[]; const origin = Array.from( new Set([...(isProduction ? [] : DEV_ORIGINS), ...configuredOrigins].filter(Boolean)) ); return [ 'strapi::logger', 'strapi::errors', // If uploads move to S3/CDN, add the bucket host to img-src and media-src // here - see the S3 notes in config/plugins.ts. 'strapi::security', { name: 'strapi::cors', config: { // An empty list blocks every cross-origin browser request, which is the // safe default if CORS_ORIGINS was forgotten in production. origin, methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'], headers: ['Content-Type', 'Authorization', 'Origin', 'Accept'], // The web app sends the locale it wants and reads pagination metadata. expose: ['Content-Range', 'Content-Length'], credentials: true, maxAge: 31536000, keepHeadersOnError: false, }, }, 'strapi::poweredBy', 'strapi::query', 'strapi::body', 'strapi::session', 'strapi::favicon', 'strapi::public', ]; }; export default config;