110 lines
4.2 KiB
Plaintext
110 lines
4.2 KiB
Plaintext
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
//#region src/middleware/cors/index.ts
|
|
/**
|
|
* CORS Middleware for Hono.
|
|
*
|
|
* @see {@link https://hono.dev/docs/middleware/builtin/cors}
|
|
*
|
|
* @param {CORSOptions} [options] - The options for the CORS middleware.
|
|
* @param {string | string[] | ((origin: string, c: Context) => Promise<string | undefined | null> | string | undefined | null)} [options.origin='*'] - The value of "Access-Control-Allow-Origin" CORS header.
|
|
* @param {string[] | ((origin: string, c: Context) => Promise<string[]> | string[])} [options.allowMethods=['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH', 'QUERY']] - The value of "Access-Control-Allow-Methods" CORS header.
|
|
* @param {string[]} [options.allowHeaders=[]] - The value of "Access-Control-Allow-Headers" CORS header.
|
|
* @param {number} [options.maxAge] - The value of "Access-Control-Max-Age" CORS header.
|
|
* @param {boolean} [options.credentials] - The value of "Access-Control-Allow-Credentials" CORS header.
|
|
* @param {string[]} [options.exposeHeaders=[]] - The value of "Access-Control-Expose-Headers" CORS header.
|
|
* @returns {MiddlewareHandler} The middleware handler function.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const app = new Hono()
|
|
*
|
|
* app.use('/api/*', cors())
|
|
* app.use(
|
|
* '/api2/*',
|
|
* cors({
|
|
* origin: 'http://example.com',
|
|
* allowHeaders: ['X-Custom-Header', 'Upgrade-Insecure-Requests'],
|
|
* allowMethods: ['POST', 'GET', 'OPTIONS'],
|
|
* exposeHeaders: ['Content-Length', 'X-Kuma-Revision'],
|
|
* maxAge: 600,
|
|
* credentials: true,
|
|
* })
|
|
* )
|
|
*
|
|
* app.all('/api/abc', (c) => {
|
|
* return c.json({ success: true })
|
|
* })
|
|
* app.all('/api2/abc', (c) => {
|
|
* return c.json({ success: true })
|
|
* })
|
|
* ```
|
|
*/
|
|
const cors = (options) => {
|
|
const opts = {
|
|
origin: "*",
|
|
allowMethods: [
|
|
"GET",
|
|
"HEAD",
|
|
"PUT",
|
|
"POST",
|
|
"DELETE",
|
|
"PATCH",
|
|
"QUERY"
|
|
],
|
|
allowHeaders: [],
|
|
exposeHeaders: [],
|
|
...options
|
|
};
|
|
const exposeHeadersStr = opts.exposeHeaders?.length ? opts.exposeHeaders.join(",") : void 0;
|
|
const allowHeadersStr = opts.allowHeaders?.length ? opts.allowHeaders.join(",") : void 0;
|
|
const findAllowOrigin = ((optsOrigin) => {
|
|
if (typeof optsOrigin === "string") {
|
|
if (optsOrigin === "*") return () => optsOrigin;
|
|
else return (origin) => optsOrigin === origin ? origin : null;
|
|
} else if (typeof optsOrigin === "function") return optsOrigin;
|
|
else return (origin) => optsOrigin.includes(origin) ? origin : null;
|
|
})(opts.origin);
|
|
const findAllowMethods = ((optsAllowMethods) => {
|
|
if (typeof optsAllowMethods === "function") return async (origin, c) => (await optsAllowMethods(origin, c)).join(",");
|
|
else if (Array.isArray(optsAllowMethods)) {
|
|
const methodsStr = optsAllowMethods.join(",");
|
|
return () => methodsStr;
|
|
} else return () => "";
|
|
})(opts.allowMethods);
|
|
return async function cors(c, next) {
|
|
function set(key, value) {
|
|
c.res.headers.set(key, value);
|
|
}
|
|
const allowOrigin = await findAllowOrigin(c.req.header("origin") || "", c);
|
|
if (allowOrigin) set("Access-Control-Allow-Origin", allowOrigin);
|
|
if (opts.credentials) set("Access-Control-Allow-Credentials", "true");
|
|
if (exposeHeadersStr) set("Access-Control-Expose-Headers", exposeHeadersStr);
|
|
if (c.req.method === "OPTIONS") {
|
|
if (opts.origin !== "*") c.res.headers.append("Vary", "Origin");
|
|
if (opts.maxAge != null) set("Access-Control-Max-Age", opts.maxAge.toString());
|
|
const allowMethods = await findAllowMethods(c.req.header("origin") || "", c);
|
|
if (allowMethods) set("Access-Control-Allow-Methods", allowMethods);
|
|
let headersStr = allowHeadersStr;
|
|
if (!headersStr) {
|
|
const requestHeaders = c.req.header("Access-Control-Request-Headers");
|
|
if (requestHeaders) headersStr = requestHeaders.split(",").map((h) => h.trim()).join(",");
|
|
}
|
|
if (headersStr) {
|
|
set("Access-Control-Allow-Headers", headersStr);
|
|
c.res.headers.append("Vary", "Access-Control-Request-Headers");
|
|
}
|
|
c.res.headers.delete("Content-Length");
|
|
c.res.headers.delete("Content-Type");
|
|
return new Response(null, {
|
|
headers: c.res.headers,
|
|
status: 204,
|
|
statusText: "No Content"
|
|
});
|
|
}
|
|
await next();
|
|
if (opts.origin !== "*") c.header("Vary", "Origin", { append: true });
|
|
};
|
|
};
|
|
//#endregion
|
|
exports.cors = cors;
|