next-armored
Version:
Security middlewares for Next.js
156 lines (150 loc) • 5.05 kB
JavaScript
import "../../chunk-7D4SUZUM.js";
// middlewares/cross-origin-resource-sharing/middleware.ts
import { NextResponse } from "next/server";
// middlewares/cross-origin-resource-sharing/config.ts
var DEFAULT_CORS_CONFIG = {
origins: void 0,
// Required -> DO NOT USE * by default
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
headers: ["Content-Type", "Authorization"],
allowCredentials: true,
preflightContinue: false,
optionsSuccessStatus: 204,
exposedHeaders: [],
maxAge: 60 * 60 * 24
// 1 day
};
// middlewares/cross-origin-resource-sharing/constants.ts
var ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
var ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
var ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
var ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
var ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
var ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
// middlewares/cross-origin-resource-sharing/utils.ts
function isPathMatching(url, pathMatcher, includeOption = "every") {
const { startWith, additionalIncludes } = pathMatcher;
const isMatching = url.startsWith(startWith);
if (isMatching && additionalIncludes !== void 0) {
if (includeOption === "every") {
return additionalIncludes.every((path) => url.includes(path));
}
return additionalIncludes.some((path) => url.includes(path));
}
return isMatching;
}
function isPathIncluded(path, pathToMatch) {
return pathToMatch.some((pathMatcher) => isPathMatching(path, pathMatcher));
}
function configureMaxAge(maxAge) {
return {
key: ACCESS_CONTROL_MAX_AGE,
value: maxAge.toString()
};
}
function configureExposedHeaders(exposedHeaders) {
return {
key: ACCESS_CONTROL_EXPOSE_HEADERS,
value: exposedHeaders.join(", ")
};
}
function configureAllowCredentials(allowCredentials) {
return {
key: ACCESS_CONTROL_ALLOW_CREDENTIALS,
value: allowCredentials ? "true" : "false"
};
}
function configureAllowMethods(methods) {
return {
key: ACCESS_CONTROL_ALLOW_METHODS,
value: methods.join(", ")
};
}
function configureAllowHeaders(headers) {
return {
key: ACCESS_CONTROL_ALLOW_HEADERS,
value: headers.join(", ")
};
}
function configureAllowOrigin(origin) {
return {
key: ACCESS_CONTROL_ALLOW_ORIGIN,
value: origin
};
}
function getIsOriginAllowed(origin, allowedOrigins) {
if (allowedOrigins.length === 0) {
return { result: false };
}
if (allowedOrigins.includes("*")) {
return { result: true, origin };
}
for (const allowedOrigin of allowedOrigins) {
if (typeof allowedOrigin === "string" && allowedOrigin === origin) {
return { result: true, origin };
}
if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
return { result: true, origin };
}
}
return { result: false };
}
// middlewares/cross-origin-resource-sharing/middleware.ts
var createCorsMiddleware = (config, pathOptions = {}) => {
const configWithDefaults = { ...DEFAULT_CORS_CONFIG, ...config };
const {
origins,
methods,
headers,
allowCredentials,
exposedHeaders,
maxAge,
optionsSuccessStatus,
preflightContinue
} = configWithDefaults;
const corsMiddleware = (request, response) => {
const nextResponse = response ?? NextResponse.next();
const pathname = request.nextUrl.pathname;
if (pathOptions.excludes !== void 0 && isPathIncluded(pathname, pathOptions.excludes)) {
return nextResponse;
}
if (pathOptions.includes !== void 0 && !isPathIncluded(pathname, pathOptions.includes)) {
return nextResponse;
}
const origin = request.headers.get("origin") ?? "";
const isOriginAllowed = getIsOriginAllowed(origin, origins);
const optionsHeaders = [];
optionsHeaders.push(configureMaxAge(maxAge));
optionsHeaders.push(configureExposedHeaders(exposedHeaders));
optionsHeaders.push(configureAllowCredentials(allowCredentials));
optionsHeaders.push(configureAllowMethods(methods));
optionsHeaders.push(configureAllowHeaders(headers));
if (isOriginAllowed.result) {
optionsHeaders.push(configureAllowOrigin(isOriginAllowed.origin));
}
const isPreflight = request.method === "OPTIONS";
if (isPreflight && !preflightContinue) {
return NextResponse.json(
{},
{
headers: optionsHeaders.map((header) => [header.key, header.value]),
status: optionsSuccessStatus
}
);
}
optionsHeaders.forEach(({ key, value }) => {
nextResponse.headers.set(key, value);
});
return nextResponse;
};
return corsMiddleware;
};
var middleware_default = createCorsMiddleware;
// middlewares/cross-origin-resource-sharing/index.ts
var cross_origin_resource_sharing_default = middleware_default;
export {
DEFAULT_CORS_CONFIG,
middleware_default as createCorsMiddleware,
cross_origin_resource_sharing_default as default
};
//# sourceMappingURL=index.js.map