cors
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.
Examples
The examples below demonstrate how you can configure routes using the cors plugin for different scenarios.
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.
- Admin API
- ADC
- Ingress Controller
Create a route with the cors plugin:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_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"
}
}'
services:
- name: cors-service
routes:
- name: cors-route
uris:
- /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:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: cors-plugin-config
spec:
plugins:
- name: cors
config:
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
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: cors-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: cors-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f cors-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: cors-route
spec:
ingressClassName: apisix
http:
- name: cors-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: cors
enable: true
config:
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
Apply the configuration to your cluster:
kubectl apply -f cors-ic.yaml
❶ allow_origins: configure allowed origins, comma-separated. To allow all origins, set it to *.
❷ max_age: configure the maximum time the result is cached in seconds.
❸ allow_credential: set to true to allow credentials (cookies, HTTP authentication, and client-side SSL certificates) to be sent with the request. If you set this to true, you cannot use * for other cors attributes.
Send a head 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 head 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 header:
...
Access-Control-Allow-Origin: http://sub3.domain.com
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
Vary: Origin
Use RegEx to Match Origin
The following example demonstrates how to use RegEx to match the origin in allow_origins using the allow_origins_by_regex field.
- Admin API
- ADC
- Ingress Controller
Create a route with the cors plugin:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_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"
}
}'
services:
- name: cors-service
routes:
- name: cors-route
uris:
- /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:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: cors-regex-plugin-config
spec:
plugins:
- name: cors
config:
allow_methods: "GET,POST"
allow_headers: "headr1,headr2"
expose_headers: "ex-headr1,ex-headr2"
max_age: 50
allow_origins_by_regex:
- ".*\\.test.com$"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: cors-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: cors-regex-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f cors-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: cors-route
spec:
ingressClassName: apisix
http:
- name: cors-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: cors
enable: true
config:
allow_methods: "GET,POST"
allow_headers: "headr1,headr2"
expose_headers: "ex-headr1,ex-headr2"
max_age: 50
allow_origins_by_regex:
- ".*\\.test.com$"
Apply the configuration to your cluster:
kubectl apply -f cors-ic.yaml
❶ allow_origins_by_regex: allow origins using RegEx. If used together with allow_origins, then allow_origins will be ignored.
Send a head 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
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
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
You can also try to make a request with an invalid origin:
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 header:
...
Access-Control-Allow-Origin: http://a.test2.com
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
Vary: Origin
Configure Origins in Plugin Metadata
The following example demonstrates how to configure origins in plugin metadata and reference them as the allowed origins in the cors plugin.
- Admin API
- ADC
- Ingress Controller
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_API_KEY}" \
-d '{
"allow_origins": {
"key_1": "https://domain.com",
"key_2": "https://sub.domain.com,https://sub2.domain.com",
"key_3": "*"
}
}'
❶ allow_origins : a map of keys and allowed origins. The key will be used to match the origin in the route.
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_API_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"
}
}'
❶ allow_origins_by_metadata: keys in the metadata to match the origin.
plugin_metadata:
cors:
allow_origins:
key_1: "https://domain.com"
key_2: "https://sub.domain.com,https://sub2.domain.com"
key_3: "*"
services:
- name: cors-service
routes:
- name: cors-route
uris:
- /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:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
Update your GatewayProxy manifest to configure the plugin metadata:
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
namespace: aic
name: apisix-config
spec:
provider:
type: ControlPlane
controlPlane:
# ...
# your control plane connection configuration
pluginMetadata:
cors:
allow_origins:
key_1: "https://domain.com"
key_2: "https://sub.domain.com,https://sub2.domain.com"
key_3: "*"
❶ allow_origins: a map of keys and allowed origins. The key will be used to match the origin in the route.
- Gateway API
- APISIX CRD
Create the route with allow_origins_by_metadata:
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: cors-metadata-plugin-config
spec:
plugins:
- name: cors
config:
allow_methods: "GET,POST"
allow_headers: "headr1,headr2"
expose_headers: "ex-headr1,ex-headr2"
max_age: 50
allow_origins_by_metadata:
- "key_1"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: cors-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: cors-metadata-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Create the route with allow_origins_by_metadata:
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: cors-route
spec:
ingressClassName: apisix
http:
- name: cors-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: cors
enable: true
config:
allow_methods: "GET,POST"
allow_headers: "headr1,headr2"
expose_headers: "ex-headr1,ex-headr2"
max_age: 50
allow_origins_by_metadata:
- "key_1"
❶ allow_origins_by_metadata: keys in the metadata to match the origin.
Apply the configuration to your cluster:
kubectl apply -f gatewayproxy.yaml -f cors-ic.yaml
Send a head 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
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
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 another request with an invalid origin:
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 header:
...
Access-Control-Allow-Origin: http://a.test2.com
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
Vary: Origin