cors-middleware
HTTP cross-origin resource sharing(CORS) middleware.
Compliant with Fetch living standard, 3.2. CORS protocol.
Middleware
For a definition of Universal HTTP middleware, see the http-middleware project.
CORS request and CORS preflight request
A CORS request is a request with an Origin header.
On the other hand, a CORS preflight request is a CORS request and satisfies the following:
- Method is
Options - Includes
Access-Control-Request-Methodheader - Includes
Access-Control-Request-Headersheader
This project provides middleware for CORS requests.
CORS request
Add a CORS header to the response in the downstream.
import {
cors,
type Handler,
} from "https://deno.land/x/cors_middleware@$VERSION/mod.ts";
import { assert } from "https://deno.land/std/testing/asserts.ts";
const middleware = cors();
const corsRequest = new Request("test:", {
headers: { origin: "<origin>" },
});
declare const handler: Handler;
const response = await middleware(corsRequest, handler);
assert(response.headers.has("access-control-allow-origin"));yield:
Access-Control-Allow-Origin: *
Vary: OriginCORS request options
| Name | Type | Description |
|---|---|---|
| allowOrigins | * | (string | RegExp )[] |
Allowed origin list. |
| allowCredentials | true | "true" |
Access-Control-Allow-Credentials |
| exposeHeaders | string[] |
Access-Control-Expose-Headers |
AllowOrigins
allowOrigins is a list of * or allowed origins.
The default is *.
If *, ACAO(*) is added to the response.
The list may consist of strings or regular expression objects.
The middleware compares the value of the Origin header with the
allowOrigins.
If a match is found, ACAM(Origin) is added to the response.
If no match, ACAM("") is added to the response.
import {
cors,
} from "https://deno.land/x/cors_middleware@$VERSION/middleware.ts";
import { assert } from "https://deno.land/std/testing/asserts.ts";
const middleware = cors({
allowOrigins: ["https://test.example", /^https:\/\/cdn\..*/],
});AllowCredentials
The allowCredentials value will serialize and added to the response as an ACAC
(Access-Control-Allow-Credentials) header.
import {
cors,
} from "https://deno.land/x/cors_middleware@$VERSION/middleware.ts";
const middleware = cors({ allowCredentials: true });yield:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Vary: OriginExposeHeaders
The value of exposeHeaders will serialize and added to the response as an ACEH
(Access-Control-Expose-Headers) header.
However, if the request is a CORS preflight request, it is not added.
import {
cors,
} from "https://deno.land/x/cors_middleware@$VERSION/middleware.ts";
const middleware = cors({ exposeHeaders: ["x-test"] });yield:
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: x-test
Vary: OriginCORS options serialization error
Each option will serialize.
If serialization fails, it throws an error as follows:
- Elements of
exposeHeadersare not<field-nameformat
import {
cors,
} from "https://deno.land/x/cors_middleware@$VERSION/middleware.ts";
import { assertThrows } from "https://deno.land/std/testing/asserts.ts";
const middleware = assertThrows(() =>
cors({ exposeHeaders: ["<invalid:field-name>"] })
);CORS preflight request
Create CORS preflight request handler.
import {
type Handler,
preflight,
} from "https://deno.land/x/cors_middleware@$VERSION/mod.ts";
import { assert } from "https://deno.land/std/testing/asserts.ts";
import { assertSpyCalls, spy } from "https://deno.land/std/testing/mock.ts";
const corsPreflightRequest = new Request("test:", {
method: "OPTIONS",
headers: {
origin: "<origin>",
"access-control-request-method": "POST",
"access-control-request-headers": "content-type",
},
});
declare const handler: Handler;
const next = spy(handler);
const handlePreflight = preflight();
const response = await handlePreflight(corsPreflightRequest, next);
assertSpyCalls(next, 0);
assert(response.status === 204);
assert(response.headers.has("access-control-allow-origin"));
assert(response.headers.has("access-control-allow-methods"));
assert(response.headers.has("access-control-allow-headers"));
assert(response.headers.has("vary"));yield:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: content-type
Vary: origin, access-control-request-method, access-control-request-headersIf the request is not a CORS preflight request, next will execute.
CORS preflight options
| Name | Type | Description |
|---|---|---|
| allowMethods | string[] |
Access-Control-Allow-Methods |
| allowHeaders | string[] |
Access-Control-Allow-Headers |
| maxAge | number |
Access-Control-Max-Age |
| status | 200 | 204 |
Preflight response status code. |
AllowMethods
The value of allowMethods will serialize and added to the response as an ACAM
(Access-Control-Allow-Methods) header.
If not specified, ACRM (Access-Control-Request-Method) will add as ACAM to the
response.
import { preflight } from "https://deno.land/x/cors_middleware@$VERSION/middleware.ts";
const handler = preflight({ allowMethods: ["POST", "PUT"] });yield:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, PUT
Access-Control-Allow-Headers: <Access-Control-Request-Headers>
Vary: origin, access-control-request-method, access-control-request-headersAllowHeaders
The value of allowHeaders will serialize and added to the response as an ACAH
(Access-Control-Allow-Headers) header.
If not specified, ACRH (Access-Control-Request-Headers) will add as ACAH to
the response.
import { preflight } from "https://deno.land/x/cors_middleware@$VERSION/middleware.ts";
const handler = preflight({ allowHeaders: ["x-test1", "x-test2"] });yield:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: <Access-Control-Request-Method>
Access-Control-Allow-Headers: x-test1, x-test2
Vary: origin, access-control-request-method, access-control-request-headersMaxAge
The value of maxAge will serialize and added to the response as an ACMA
(Access-Control-Max-Age) header.
import { preflight } from "https://deno.land/x/cors_middleware@$VERSION/middleware.ts";
const handler = preflight({ maxAge: 86400 });yield:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: <Access-Control-Request-Method>
Access-Control-Allow-Headers: <Access-Control-Request-Headers>
Access-Control-Max-Age: 86400
Vary: origin, access-control-request-method, access-control-request-headersStatus
The default is 204 No Content.
You can change to 200 OK.
API
All APIs can be found in the deno doc.
License
Copyright © 2023-present httpland.
Released under the MIT license
