cors
Adds CORS headers so browsers can call the API from other origins.
corsPriority 4000What it does
cors adds the headers a browser needs to let a page on another origin call your API. On the route, the origins go under Allow origins, with the methods and request headers they may use beside them. A request whose Origin is on the list is answered with that origin in Access-Control-Allow-Origin.
Allow credential lets browsers send cookies and authorization headers across origins, and then a * in any list is refused when you save. Switching it on alone is refused as well, because Allow origins, Allow methods and Allow headers read * until you name them.
When to use it
- A web app at
https://app.example.comthat calls the orders API from the browser with the user's session cookie. - Several storefront sites that share one list of origins, kept once in plugin metadata and picked by name on each route.
- Preview sites, one subdomain each, admitted by one pattern under Allow origins by regex instead of a list that changes every week.
- A response header the browser app must read,
X-Request-Idfor example, named under Expose headers.
Not for deciding which clients may call the API at all — see key-auth (Authenticates consumers with an API key sent in a header or query parameter) or refusing forged writes that ride on a browser's cookies — see csrf (Protects state-changing requests against cross-site request forgery).
Guides
Pages that walk through a job with cors, step by step.
- Let a browser app call the APIPut cors on a route so a web app served from another origin can call the API from the browser, cookies included.
Set it up
Let a browser app on another origin call the API with cookies
Under Basics set Allow origins to https://app.example.com, turn on Allow credential, set Allow methods to GET,POST,PUT,DELETE and set Allow headers to Authorization,Content-Type. Under Behavior set Expose headers to X-Request-Id and set Preflight cache time to 3600 seconds.
{
"allow_origins": "https://app.example.com",
"allow_methods": "GET,POST,PUT,DELETE",
"allow_headers": "Authorization,Content-Type",
"allow_credential": true,
"expose_headers": "X-Request-Id",
"max_age": 3600
}
What you will see
- A request from the page at
https://app.example.comis answered200withAccess-Control-Allow-Origin: https://app.example.com, so the browser lets the page read the answer. - The same answer carries
Access-Control-Allow-Credentials: true, so the browser sends the cookies of the API with the request and accepts the ones it sets. - The same answer carries
Access-Control-Expose-Headers: X-Request-Id, so the page may read that header; every other header of the answer stays hidden from it. - The preflight the browser sends before a
POST, an OPTIONS request naming the method it wants, is answered200by the gateway withAccess-Control-Allow-Methods: GET,POST,PUT,DELETE. - The same preflight answer carries
Access-Control-Allow-Headers: Authorization,Content-Type, the request headers the page may send. - The same preflight answer carries
Access-Control-Max-Age: 3600, so the browser keeps the preflight answer for an hour and asks again only after that.
More scenarios
Keep named sets of allowed origins that routes can pick by nameenvironment-wide settings
Fill Allow origins as in the JSON below.
{
"allow_origins": {
"storefront": "https://shop.example.com,https://www.example.com",
"partners": "https://portal.partner.example.com"
}
}
What you will see
- On a route whose cors plugin names the set storefront, a request from
https://shop.example.comis answered200withAccess-Control-Allow-Origin: https://shop.example.com. - A request from
https://www.example.com, the other origin of the same set, is answered200withAccess-Control-Allow-Origin: https://www.example.com.
Things to know
- Allow origins — With
https://app.example.comlisted, a request from that origin is answered200withhttps://app.example.cominAccess-Control-Allow-Origin. - Allow origins — An entry is a whole origin with its scheme;
a.testis refused when you save. - Allow origins —
**admits any origin even with credentials, which opens the service to any site. - Allow credential — On, a request from a listed origin is answered with
Access-Control-Allow-Credentialsset totruebeside its origin. - Allow credential — On by itself, it is refused when you save: the three lists of the first section read
*until you name them, and a*is refused beside credentials. - Allow methods — An
OPTIONSrequest from a listed origin is answered200with this list inAccess-Control-Allow-Methods,GET,POST,PUT,DELETEin the example. - Expose headers — With Allow credential on, a
*here is refused when you save as well. Name the headers one by one. - Allow origins by regex — A pattern that is not anchored matches anywhere in the origin. A matching origin is echoed back, credentials included, and Allow origins is then ignored.
- Allow origins by metadata — Each name picks a set kept under Allow origins in the cors plugin metadata of the environment. With
storefrontholding two origins, a request from either is answered with its own origin inAccess-Control-Allow-Origin. - Preflight cache time — Browsers cap the value at a ceiling of their own.
- Allow headers — A preflight from a listed origin is answered with this list in
Access-Control-Allow-Headers,Authorization,Content-Typein the example. - Preflight cache time — The preflight answer carries the value in
Access-Control-Max-Age,3600in the example, so the browser asks again only after that many seconds. - Expose headers — An answer to a listed origin carries this list in
Access-Control-Expose-Headers,X-Request-Idin the example, so the page's script may read those headers. - AdviceWhere cookies travel, list the origins of your own web apps by name and keep
**out of the route.
Settings
The fields as the console shows them, section by section.
Basics
allow_originsstringdefault *The origins allowed to call, comma separated, such as https://app.example.com, where * allows any origin without credentials. ** allows any origin even with credentials, which opens the service to any site.
pattern
^(\*|\*\*|null|\w+://[^,]+(,\w+://[^,]+)*)$allow_credentialbooleandefault falseLets browsers send cookies and authorization headers across origins, and needs explicit origins, methods and headers because their star default is refused.
allow_methodsstringdefault *The methods allowed across origins, comma separated, such as GET,POST, where * allows all of them without credentials. ** allows all of them even with credentials.
allow_headersstringdefault *The request headers allowed across origins, comma separated, such as Authorization,Content-Type, where * allows all without credentials. ** allows all of them even with credentials.
Behavior
allow_origins_by_regexarray of stringsRegular expressions the request's origin must match, anchored with ^ and $, such as ^https://[a-z0-9-]+\.example\.com$. An unanchored pattern matches anywhere, so example\.com also admits https://example.com.evil.org. A matching origin is echoed back, credentials included, and Allow origins is then ignored.
expose_headersstringResponse headers the browser may read across origins, comma separated, where empty exposes only the safe set.
X-Request-Id,X-Trace-Idmax_ageintegerdefault 5How long a browser may cache a preflight answer, where -1 turns that caching off. Browsers cap the value at a ceiling of their own.
Advanced
allow_origins_by_metadataarray of stringsNames of origin lists kept in this plugin's environment-wide metadata, used as allowed origins.
timing_allow_originsstringOrigins that may read the response's timing details, comma separated, where * allows every origin without credentials. ** allows every origin even with credentials, which weakens the protection.
pattern
^(\*|\*\*|null|\w+://[^,]+(,\w+://[^,]+)*)$timing_allow_origins_by_regexarray of stringsRegular expressions matched against the origin, one per entry, where a match may read the response's timing details.
Environment-wide settings
Set once per environment, under Plugins › cors. Every cors in the environment uses these.
allow_originsobjectAn object whose keys are any name, each with a string as its value.