Setting up CORS for the APIs
Setting up CORS for a resource (route) in API Gateway is done by specifying an extra route for the same route
,
with OPTIONS
method, and will serve the browser's preflight request.
By adding this route, all the routes with the same resource (route) ha will be automatically enabled with CORS. In other words, all the operations under the resource will be enabled with CORS.
Default CORS
Here is a complete example where /v1/{user}/checkout
resource is CORS enabled.
# Schema for IDEA:
# $schema: https://schema.golem.cloud/app/golem/1.2.2-dev.1/golem.schema.json
# Schema for vscode-yaml
# yaml-language-server: $schema=https://schema.golem.cloud/app/golem/1.2.2-dev.1/golem.schema.json
# See https://learn.golem.cloud/docs/app-manifest#field-reference for field reference
components:
amazon:shopping-cart:
template: rust
httpApi:
definitions:
shopping-cart:
version: '0.0.5'
routes:
- method: OPTIONS
path: /v1/{user}/checkout
binding:
type: cors-preflight
- method: POST
path: /v1/{user}/add-to-cart
binding:
type: default
componentName: "amazon:shopping-cart"
response: |
let user: u32 = request.path.user;
let worker = instance("cart-${user}");
worker.add-item(request.body);
"successfully added item to the cart"
- method: GET
path: /v1/{user}/contents
security: my-security
binding:
type: default
componentName: "amazon:shopping-cart"
response: |
let user: u32 = request.path.user;
let worker = instance("cart-${user}");
let user-name: string = request.auth.email;
{
user: user-name,
cart: worker.get-cart-contents()
}
- method: POST
path: /v1/{user}/checkout
binding:
type: default
componentName: "amazon:shopping-cart"
response: |
let user: u32 = request.path.user;
let worker = instance("cart-${user}");
worker.checkout()
# Uncomment if you want to deploy your api
deployments:
local:
- host: localhost:9006
definitions:
- shopping-cart
Here, we define the preflight request endpoint for /v1/{user}/checkout
as the OPTIONS method.
This is used by browsers to check if the actual request is allowed.
- method: OPTIONS
path: /v1/{user}/checkout
binding:
type: cors-preflight
As mentioned before, this additional route will ensure that the other operations (in the above example, GET) will also be CORS-enabled with the required headers in the response.
You can simulate a preflight request and test this
curl -X OPTIONS http://localhost:9006/v1/100/checkout \
-H "Origin: https://myfrontend.com" \
-H "Access-Control-Request-Method: PUT" \
-H "Access-Control-Request-Headers: Authorization, Content-Type" \
-i
HTTP/1.1 200 OK
access-control-allow-origin: *
access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
access-control-allow-headers: Content-Type, Authorization
access-control-expose-headers: Content-Length, X-Requested-With
access-control-allow-credentials: true
access-control-max-age: 86400
content-length: 0
date: Tue, 13 May 2025 23:55:01 GMT
curl -X POST http://localhost:9006/v1/100/checkout -H "origin: localhost" Tue 13 May 17:55:01 2025
{"success":{"order-id":"238738674"}}⏎
Customised CORS
But we can customise this behaviour further by providing custom CORS set up by doing the following
- method: OPTIONS
path: /v1/{user}/checkout
binding:
type: cors-preflight
response: |
{
Access-Control-Allow-Origin: "*",
Access-Control-Allow-Methods: "GET, POST, PUT, DELETE, OPTIONS",
Access-Control-Allow-Headers: "Content-Type, Authorization",
Access-Control-Expose-Headers: "Content-Length, X-Requested-With",
Access-Control-Allow-Credentials: true,
Access-Control-Max-Age: 86400u64
}
Here is the full example
We can define a custom response for the preflight request as well using Rib as given below.
Her we changed the origins to be mysite.com
instead of *
# Schema for IDEA:
# $schema: https://schema.golem.cloud/app/golem/1.2.2-dev.1/golem.schema.json
# Schema for vscode-yaml
# yaml-language-server: $schema=https://schema.golem.cloud/app/golem/1.2.2-dev.1/golem.schema.json
# See https://learn.golem.cloud/docs/app-manifest#field-reference for field reference
components:
amazon:shopping-cart:
template: rust
httpApi:
definitions:
shopping-cart:
version: '0.0.7'
routes:
- method: OPTIONS
path: /v1/{user}/checkout
binding:
type: cors-preflight
response: |
{
Access-Control-Allow-Origin: "mysite.com",
Access-Control-Allow-Methods: "GET, POST, PUT, DELETE, OPTIONS",
Access-Control-Allow-Headers: "Content-Type, Authorization",
Access-Control-Expose-Headers: "Content-Length, X-Requested-With",
Access-Control-Allow-Credentials: true,
Access-Control-Max-Age: 86400u64
}
- method: POST
path: /v1/{user}/add-to-cart
binding:
type: default
componentName: "amazon:shopping-cart"
response: |
let user: u32 = request.path.user;
let worker = instance("cart-${user}");
worker.add-item(request.body);
"successfully added item to the cart"
- method: GET
path: /v1/{user}/contents
security: my-security
binding:
type: default
componentName: "amazon:shopping-cart"
response: |
let user: u32 = request.path.user;
let worker = instance("cart-${user}");
let user-name: string = request.auth.email;
{
user: user-name,
cart: worker.get-cart-contents()
}
- method: POST
path: /v1/{user}/checkout
binding:
type: default
componentName: "amazon:shopping-cart"
response: |
let user: u32 = request.path.user;
let worker = instance("cart-${user}");
worker.checkout()
# Uncomment if you want to deploy your api
deployments:
local:
- host: localhost:9006
definitions:
- shopping-cart
golem api deploy
The allowed origin is only mysite.com
as per the API definition, and if the origin is different it should result in "origin not allowed"
curl -X POST http://localhost:9006/v1/100/checkout -H "origin: notmysite.com"
CORS Error: Origin not allowed
curl -X POST http://localhost:9006/v1/100/checkout -H "origin: mysite.com" Tue 13 May 17:59:13 2025
{"success":{"order-id":"238738674"}}