Skip to main content
Version: Next

cors

Description#

The cors Plugin allows you to enable Cross-Origin Resource Sharing (CORS). CORS is an HTTP-header based mechanism which allows a server to specify any origins (domain, scheme, or port) other than its own, and instructs browsers to allow the loading of resources from those origins.

Attributes#

NameTypeRequiredDefaultValid valuesDescription
allow_originsstringFalse"*"Comma-separated string of origins to allow CORS, in the format scheme://host:port, for example https://somedomain.com:8081. If you have multiple origins, use , to list them. If allow_credential is set to false, you can use * to allow all origins. If allow_credential is set to true, you can use ** to forcefully allow all origins, but this poses security risks.
allow_methodsstringFalse"*"Comma-separated string of HTTP request methods to allow CORS, for example GET, POST. If allow_credential is set to false, you can use * to allow all methods. If allow_credential is set to true, you can use ** to forcefully allow all methods, but this poses security risks.
allow_headersstringFalse"*"Comma-separated string of HTTP headers allowed in requests when accessing a cross-origin resource. If allow_credential is set to false, you can use * to allow all request headers. If allow_credential is set to true, you can use ** to forcefully allow all request headers, but this poses security risks.
expose_headersstringFalseComma-separated string of HTTP headers that should be made available in response to a cross-origin request. If allow_credential is set to false, you can use * to allow all response headers. If not specified, the Plugin will not modify the Access-Control-Expose-Headers header. See Access-Control-Expose-Headers - MDN for more details.
max_ageintegerFalse5Maximum time in seconds for which the results of a preflight request can be cached. If the time is within this limit, the browser will check the cached result. Set to -1 to disable caching. Note that the maximum value is browser-dependent. See Access-Control-Max-Age for more details.
allow_credentialbooleanFalsefalseWhen set to true, allows requests to include credentials such as cookies. According to CORS specification, if you set this to true, you cannot use * for other CORS attributes.
allow_origins_by_regexarrayFalseRegex to match origins that allow CORS. For example, [".*\.test.com$"] can match all subdomains of test.com. When configured, only domains matching the RegEx will be allowed and allow_origins will be ignored.
allow_origins_by_metadataarrayFalseOrigins to enable CORS referenced from allow_origins set in the Plugin metadata. For example, if "allow_origins": {"EXAMPLE": "https://example.com"} is set in the Plugin metadata, then ["EXAMPLE"] can be used to allow CORS on the origin https://example.com.
timing_allow_originsstringFalseComma-separated string of origins to allow access to the resource timing information. See Timing-Allow-Origin for more details.
timing_allow_origins_by_regexarrayFalseRegex to match origins for enabling access to the resource timing information. For example, [".*\.test.com"] can match all subdomains of test.com. When configured, only domains matching the RegEx will be allowed and timing_allow_origins will be ignored.
IMPORTANT
  1. The allow_credential attribute is sensitive and must be used carefully. If set to true, the default value * of the other attributes will be invalid and they should be specified explicitly.
  2. When using ** you are vulnerable to security risks like CSRF. Make sure that this meets your security levels before using it.

Metadata#

NameTypeRequiredDefaultValid valuesDescription
allow_originsobjectFalseA map of keys and allowed origins. The keys are used in the allow_origins_by_metadata attribute and the values are equivalent to the allow_origins attribute of the Plugin.

Examples#

The examples below demonstrate how you can configure the cors Plugin for different scenarios.

note

You can fetch the admin_key from config.yaml and save to an environment variable with the following command:

admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')

Enable CORS for a Route#

The following example demonstrates how to enable CORS on a Route to allow resource loading from a list of origins.

Create a Route with the cors Plugin:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cors-route",
"uri": "/anything",
"plugins": {
"cors": {
"allow_origins": "http://sub.domain.com,http://sub2.domain.com",
"allow_methods": "GET,POST",
"allow_headers": "headr1,headr2",
"expose_headers": "ex-headr1,ex-headr2",
"max_age": 50,
"allow_credential": true
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}'

Send a request to the Route with an allowed origin:

curl "http://127.0.0.1:9080/anything" -H "Origin: http://sub2.domain.com" -I

You should receive an HTTP/1.1 200 OK response and observe CORS headers:

...
Access-Control-Allow-Origin: http://sub2.domain.com
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
Vary: Origin
Access-Control-Allow-Methods: GET,POST
Access-Control-Max-Age: 50
Access-Control-Expose-Headers: ex-headr1,ex-headr2
Access-Control-Allow-Headers: headr1,headr2

Send a request to the Route with an origin that is not allowed:

curl "http://127.0.0.1:9080/anything" -H "Origin: http://sub3.domain.com" -I

You should receive an HTTP/1.1 200 OK response without any CORS headers:

...
Server: APISIX/3.8.0
Vary: Origin

Use RegEx to Match Origin#

The following example demonstrates how to use a regular expression to match allowed origins using the allow_origins_by_regex attribute.

Create a Route with the cors Plugin:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cors-route",
"uri": "/anything",
"plugins": {
"cors": {
"allow_methods": "GET,POST",
"allow_headers": "headr1,headr2",
"expose_headers": "ex-headr1,ex-headr2",
"max_age": 50,
"allow_origins_by_regex": [ ".*\\.test.com$" ]
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}'

Send a request to the Route with an allowed origin:

curl "http://127.0.0.1:9080/anything" -H "Origin: http://a.test.com" -I

You should receive an HTTP/1.1 200 OK response and observe CORS headers:

...
Access-Control-Allow-Origin: http://a.test.com
Server: APISIX/3.8.0
Vary: Origin
Access-Control-Allow-Methods: GET,POST
Access-Control-Max-Age: 50
Access-Control-Expose-Headers: ex-headr1,ex-headr2
Access-Control-Allow-Headers: headr1,headr2

Send a request with an origin that does not match the pattern:

curl "http://127.0.0.1:9080/anything" -H "Origin: http://a.test2.com" -I

You should receive an HTTP/1.1 200 OK response without any CORS headers:

...
Server: APISIX/3.8.0
Vary: Origin

Configure Origins in Plugin Metadata#

The following example demonstrates how to configure allowed origins in Plugin metadata and reference them in the cors Plugin using allow_origins_by_metadata.

Configure Plugin metadata for the cors Plugin:

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/cors" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"allow_origins": {
"key_1": "https://domain.com",
"key_2": "https://sub.domain.com,https://sub2.domain.com",
"key_3": "*"
}
}'

Create a Route with the cors Plugin using allow_origins_by_metadata:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "cors-route",
"uri": "/anything",
"plugins": {
"cors": {
"allow_methods": "GET,POST",
"allow_headers": "headr1,headr2",
"expose_headers": "ex-headr1,ex-headr2",
"max_age": 50,
"allow_origins_by_metadata": ["key_1"]
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}'

Send a request to the Route with an allowed origin:

curl "http://127.0.0.1:9080/anything" -H "Origin: https://domain.com" -I

You should receive an HTTP/1.1 200 OK response and observe CORS headers:

...
Access-Control-Allow-Origin: https://domain.com
Server: APISIX/3.8.0
Vary: Origin
Access-Control-Allow-Methods: GET,POST
Access-Control-Max-Age: 50
Access-Control-Expose-Headers: ex-headr1,ex-headr2
Access-Control-Allow-Headers: headr1,headr2

Send a request with an origin not in the metadata:

curl "http://127.0.0.1:9080/anything" -H "Origin: http://a.test2.com" -I

You should receive an HTTP/1.1 200 OK response without any CORS headers:

...
Server: APISIX/3.8.0
Vary: Origin