Buckets:
ktongue/docker_container / .cache /opencode /node_modules /hono /dist /middleware /secure-headers /secure-headers.js
| // src/middleware/secure-headers/secure-headers.ts | |
| import { encodeBase64 } from "../../utils/encode.js"; | |
| var HEADERS_MAP = { | |
| crossOriginEmbedderPolicy: ["Cross-Origin-Embedder-Policy", "require-corp"], | |
| crossOriginResourcePolicy: ["Cross-Origin-Resource-Policy", "same-origin"], | |
| crossOriginOpenerPolicy: ["Cross-Origin-Opener-Policy", "same-origin"], | |
| originAgentCluster: ["Origin-Agent-Cluster", "?1"], | |
| referrerPolicy: ["Referrer-Policy", "no-referrer"], | |
| strictTransportSecurity: ["Strict-Transport-Security", "max-age=15552000; includeSubDomains"], | |
| xContentTypeOptions: ["X-Content-Type-Options", "nosniff"], | |
| xDnsPrefetchControl: ["X-DNS-Prefetch-Control", "off"], | |
| xDownloadOptions: ["X-Download-Options", "noopen"], | |
| xFrameOptions: ["X-Frame-Options", "SAMEORIGIN"], | |
| xPermittedCrossDomainPolicies: ["X-Permitted-Cross-Domain-Policies", "none"], | |
| xXssProtection: ["X-XSS-Protection", "0"] | |
| }; | |
| var DEFAULT_OPTIONS = { | |
| crossOriginEmbedderPolicy: false, | |
| crossOriginResourcePolicy: true, | |
| crossOriginOpenerPolicy: true, | |
| originAgentCluster: true, | |
| referrerPolicy: true, | |
| strictTransportSecurity: true, | |
| xContentTypeOptions: true, | |
| xDnsPrefetchControl: true, | |
| xDownloadOptions: true, | |
| xFrameOptions: true, | |
| xPermittedCrossDomainPolicies: true, | |
| xXssProtection: true, | |
| removePoweredBy: true, | |
| permissionsPolicy: {} | |
| }; | |
| var generateNonce = () => { | |
| const arrayBuffer = new Uint8Array(16); | |
| crypto.getRandomValues(arrayBuffer); | |
| return encodeBase64(arrayBuffer.buffer); | |
| }; | |
| var NONCE = (ctx) => { | |
| const key = "secureHeadersNonce"; | |
| const init = ctx.get(key); | |
| const nonce = init || generateNonce(); | |
| if (init == null) { | |
| ctx.set(key, nonce); | |
| } | |
| return `'nonce-${nonce}'`; | |
| }; | |
| var secureHeaders = (customOptions) => { | |
| const options = { ...DEFAULT_OPTIONS, ...customOptions }; | |
| const headersToSet = getFilteredHeaders(options); | |
| const callbacks = []; | |
| if (options.contentSecurityPolicy) { | |
| const [callback, value] = getCSPDirectives(options.contentSecurityPolicy); | |
| if (callback) { | |
| callbacks.push(callback); | |
| } | |
| headersToSet.push(["Content-Security-Policy", value]); | |
| } | |
| if (options.contentSecurityPolicyReportOnly) { | |
| const [callback, value] = getCSPDirectives(options.contentSecurityPolicyReportOnly); | |
| if (callback) { | |
| callbacks.push(callback); | |
| } | |
| headersToSet.push(["Content-Security-Policy-Report-Only", value]); | |
| } | |
| if (options.permissionsPolicy && Object.keys(options.permissionsPolicy).length > 0) { | |
| headersToSet.push([ | |
| "Permissions-Policy", | |
| getPermissionsPolicyDirectives(options.permissionsPolicy) | |
| ]); | |
| } | |
| if (options.reportingEndpoints) { | |
| headersToSet.push(["Reporting-Endpoints", getReportingEndpoints(options.reportingEndpoints)]); | |
| } | |
| if (options.reportTo) { | |
| headersToSet.push(["Report-To", getReportToOptions(options.reportTo)]); | |
| } | |
| return async function secureHeaders2(ctx, next) { | |
| const headersToSetForReq = callbacks.length === 0 ? headersToSet : callbacks.reduce((acc, cb) => cb(ctx, acc), headersToSet); | |
| await next(); | |
| setHeaders(ctx, headersToSetForReq); | |
| if (options?.removePoweredBy) { | |
| ctx.res.headers.delete("X-Powered-By"); | |
| } | |
| }; | |
| }; | |
| function getFilteredHeaders(options) { | |
| return Object.entries(HEADERS_MAP).filter(([key]) => options[key]).map(([key, defaultValue]) => { | |
| const overrideValue = options[key]; | |
| return typeof overrideValue === "string" ? [defaultValue[0], overrideValue] : defaultValue; | |
| }); | |
| } | |
| function getCSPDirectives(contentSecurityPolicy) { | |
| const callbacks = []; | |
| const resultValues = []; | |
| for (const [directive, value] of Object.entries(contentSecurityPolicy)) { | |
| const valueArray = Array.isArray(value) ? value : [value]; | |
| valueArray.forEach((value2, i) => { | |
| if (typeof value2 === "function") { | |
| const index = i * 2 + 2 + resultValues.length; | |
| callbacks.push((ctx, values) => { | |
| values[index] = value2(ctx, directive); | |
| }); | |
| } | |
| }); | |
| resultValues.push( | |
| directive.replace( | |
| /[A-Z]+(?![a-z])|[A-Z]/g, | |
| (match, offset) => offset ? "-" + match.toLowerCase() : match.toLowerCase() | |
| ), | |
| ...valueArray.flatMap((value2) => [" ", value2]), | |
| "; " | |
| ); | |
| } | |
| resultValues.pop(); | |
| return callbacks.length === 0 ? [void 0, resultValues.join("")] : [ | |
| (ctx, headersToSet) => headersToSet.map((values) => { | |
| if (values[0] === "Content-Security-Policy" || values[0] === "Content-Security-Policy-Report-Only") { | |
| const clone = values[1].slice(); | |
| callbacks.forEach((cb) => { | |
| cb(ctx, clone); | |
| }); | |
| return [values[0], clone.join("")]; | |
| } else { | |
| return values; | |
| } | |
| }), | |
| resultValues | |
| ]; | |
| } | |
| function getPermissionsPolicyDirectives(policy) { | |
| return Object.entries(policy).map(([directive, value]) => { | |
| const kebabDirective = camelToKebab(directive); | |
| if (typeof value === "boolean") { | |
| return `${kebabDirective}=${value ? "*" : "none"}`; | |
| } | |
| if (Array.isArray(value)) { | |
| if (value.length === 0) { | |
| return `${kebabDirective}=()`; | |
| } | |
| if (value.length === 1 && (value[0] === "*" || value[0] === "none")) { | |
| return `${kebabDirective}=${value[0]}`; | |
| } | |
| const allowlist = value.map((item) => ["self", "src"].includes(item) ? item : `"${item}"`); | |
| return `${kebabDirective}=(${allowlist.join(" ")})`; | |
| } | |
| return ""; | |
| }).filter(Boolean).join(", "); | |
| } | |
| function camelToKebab(str) { | |
| return str.replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase(); | |
| } | |
| function getReportingEndpoints(reportingEndpoints = []) { | |
| return reportingEndpoints.map((endpoint) => `${endpoint.name}="${endpoint.url}"`).join(", "); | |
| } | |
| function getReportToOptions(reportTo = []) { | |
| return reportTo.map((option) => JSON.stringify(option)).join(", "); | |
| } | |
| function setHeaders(ctx, headersToSet) { | |
| headersToSet.forEach(([header, value]) => { | |
| ctx.res.headers.set(header, value); | |
| }); | |
| } | |
| export { | |
| NONCE, | |
| secureHeaders | |
| }; | |
Xet Storage Details
- Size:
- 6 kB
- Xet hash:
- 5ad61e5ea50aae4e9ea2dde874dd0b989d0c92db7f1bd5cadc3f417489262413
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.