cors with apigw
Tags: aws, apigateway, cors, cloudformation
Published: 2020-12-21 08:02:48

# cors with apigw

🌐🔗🌒🐙

lets assume a freshly mounted apigw with a resource `/pitbulls` having two endpoints serving and accepting json:

`GET /pitbulls`

`POST /pitbulls`

once you start hitting these from a browser they need to have cors enabled..

## determining cors request types

there are two types of cors requests: simple and non-simple - refer to these [AWS docs](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html) [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests) 4 specifics.

a simple requests has the following characteristics:

+ `GET`, `HEAD`, or `POST`

+ if `POST` the request must include an origin header

+ request payload content type is `text/plain`, `multipart/form-data`, or `application/x-www-form-urlencoded`

+ no custom headers

## steps 2 enable cors

### 4 simple requests

scenario: `GET /pitbulls`

the backend response must include an `Access-Control-Allow-Origin` header granting access to the request's origin domain. Note that one should specify protocol, domain, and port when defining the origin.

**backend response to a simple cors request**

```js
return {
  statusCode: 200,
  headers: {
    "access-control-allow-origin": "https://your.domain:443",
    "content-type": "application/json"
  },
  body: '[{"name":"dogo"}]'
}
```

### 4 non-simple requests

scenario: `POST /pitbulls` with request payload `content-type: application/json`

our `pitbulls` resource needs to expose an `OPTIONS` method that responds to cors preflight requests with the following cors headers: `Access-Control-Allow-Methods` `Access-Control-Allow-Headers` `Access-Control-Allow-Origin`

**cors options method snippet in cloudformation**

```yml
CorsMethod:
  Type: AWS::ApiGateway::Method
  Properties:
    AuthorizationType: NONE
    RestApiId: !Ref RestApi
    ResourceId: !Ref PitbullsResource
    HttpMethod: OPTIONS
    Integration:
      Type: MOCK
      IntegrationResponses:
        - StatusCode: 200
          ResponseParameters:
            method.response.header.Access-Control-Allow-Headers: "'content-type'"
            method.response.header.Access-Control-Allow-Methods: "'OPTIONS,GET,POST'"
            method.response.header.Access-Control-Allow-Origin: !If
              - IsProd
              - "'https://your.domain:443'"
              - "'*'"
          ResponseTemplates:
            application/json: ''
      PassthroughBehavior: WHEN_NO_MATCH
      RequestTemplates:
        'application/json': '{"statusCode":200}'
    MethodResponses:
      - StatusCode: 200
        ResponseModels:
          application/json: Empty
        ResponseParameters:
          method.response.header.Access-Control-Allow-Headers: False
          method.response.header.Access-Control-Allow-Methods: False
          method.response.header.Access-Control-Allow-Origin: False

```

Additionally, the backend, lambdas, ec2s or whatever, need to also respond with the three cors headers listed above.

**backend responding to a non-simple cors request with mandated headers**

```js
return {
  statusCode: 201,
  headers: {
    "access-control-allow-headers": "content-type",
    "access-control-allow-methods": "OPTIONS,POST",
    "access-control-allow-origin": "https://your.domain:443",
  },
}
```

🐙🌐🔗🌒 ~ AWS API Gateway CORS