UNPKG

@tanstack/start-client-core

Version:

Modern and scalable routing for React applications

63 lines (62 loc) 2.79 kB
import { createMiddleware } from "./createMiddleware.js"; import { createIsomorphicFn } from "@tanstack/start-fn-stubs"; //#region src/createCsrfMiddleware.ts var csrfSymbol = Symbol.for("tanstack-start:csrf-middleware"); var innerCreateCsrfMiddleware = (opts = {}) => { const middleware = createMiddleware().server(async (ctx) => { const csrfCtx = ctx; if (opts.filter && !await opts.filter(csrfCtx)) return ctx.next(); if (await isCsrfRequestAllowed(opts, csrfCtx)) return ctx.next(); return getFailureResponse(opts, csrfCtx); }); if (process.env.NODE_ENV !== "production") Object.defineProperty(middleware, csrfSymbol, { value: true }); return middleware; }; var createCsrfMiddleware = createIsomorphicFn().server(innerCreateCsrfMiddleware); async function isCsrfRequestAllowed(opts, ctx) { const result = await getCsrfRequestValidationResult(opts, ctx); return result === true || result === void 0 && opts.allowRequestsWithoutOriginCheck === true; } async function getCsrfRequestValidationResult(opts, ctx) { const fetchSite = ctx.request.headers.get("Sec-Fetch-Site"); if (fetchSite !== null) return matchValue(opts.secFetchSite ?? "same-origin", fetchSite, ctx); const origin = ctx.request.headers.get("Origin"); if (origin !== null) { if (opts.origin) return matchValue(opts.origin, origin, ctx); return origin === new URL(ctx.request.url).origin; } const referer = ctx.request.headers.get("Referer"); if (referer === null || opts.referer === false) return; if (typeof opts.referer === "function") return opts.referer(referer, ctx); if (opts.origin) { const refererOrigin = getOriginFromUrl(referer); return refererOrigin !== void 0 && matchValue(opts.origin, refererOrigin, ctx); } return isRefererSameOrigin(referer, new URL(ctx.request.url).origin); } async function matchValue(matcher, value, ctx) { if (typeof matcher === "function") return matcher(value, ctx); if (Array.isArray(matcher)) return matcher.includes(value); return value === matcher; } function getOriginFromUrl(url) { try { return new URL(url).origin; } catch { return; } } function isRefererSameOrigin(referer, requestOrigin) { if (referer === requestOrigin) return true; if (!referer.startsWith(requestOrigin)) return false; if (referer.length === requestOrigin.length) return true; const code = referer.charCodeAt(requestOrigin.length); return code === 47 || code === 63 || code === 35; } async function getFailureResponse(opts, ctx) { if (typeof opts.failureResponse === "function") return opts.failureResponse(ctx); return opts.failureResponse?.clone() ?? new Response("Forbidden", { status: 403 }); } //#endregion export { createCsrfMiddleware, csrfSymbol, getCsrfRequestValidationResult, isCsrfRequestAllowed }; //# sourceMappingURL=createCsrfMiddleware.js.map