Welcome to the new Golem Cloud Docs! 👋

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"}}