

# API Gateway での REST API の CORS
<a name="how-to-cors"></a>

[Cross-origin resource sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) は、ブラウザで実行されているスクリプトから開始されるクロスオリジン HTTP リクエストを制限するブラウザのセキュリティ機能です。詳細については、「[CORS とは](https://aws.amazon.com/what-is/cross-origin-resource-sharing/)」を参照してください。

## CORS サポートを有効にするかどうかを決定する
<a name="apigateway-cors-request-types"></a>

*クロスオリジン* HTTP リクエストは、以下に対して行われます。
+ 別の*ドメイン* (例: `example.com` から `amazondomains.com` へ)
+ 別の*サブドメイン* (例: `example.com` から `petstore.example.com` へ)
+ 別の*ポート* (例: `example.com` から `example.com:10777` へ)
+ 別の*プロトコル* (例: `https://example.com` から `http://example.com` へ)

 API にアクセスできず、`Cross-Origin Request Blocked` を含むエラーメッセージが表示される場合は、CORS を有効にする必要がある場合があります。

クロスオリジン HTTP リクエストは、*シンプルな*リクエスト、および*シンプルではない*リクエストの 2 種類に分類できます。

## シンプルなリクエストの CORS を有効にする
<a name="apigateway-cors-simple-request"></a>

以下の条件がすべて当てはまる場合、HTTP リクエストは*シンプル*です。
+ `GET`、`HEAD`、および `POST` のリクエストのみを許可する API リソースに対して発行されます。
+ それが `POST` メソッドリクエストの場合、`Origin` ヘッダーを含める必要があります。
+ リクエストのペイロードコンテンツタイプが `text/plain`、`multipart/form-data`、または `application/x-www-form-urlencoded` の場合。
+ リクエストにカスタムヘッダーが含まれていません。
+ [シンプルなリクエストに関する Mozilla CORS のドキュメント](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests)に一覧表示されている追加要件。

シンプルなクロスオリジンの `POST` メソッドリクエストの場合、リソースからのレスポンスにはヘッダー `Access-Control-Allow-Origin: '*'` または `Access-Control-Allow-Origin:{{'origin'}}` を含める必要があります。

他のすべてのクロスオリジン HTTP リクエストは*シンプルではない*リクエストです。

## シンプルではないリクエストの CORS を有効にする
<a name="apigateway-enable-cors-non-simple"></a>

API のリソースがシンプルではないリクエストを受け取った場合は、統合タイプに応じて追加の CORS サポートを有効にする必要があります。

### 非プロキシ統合の CORS を有効にする
<a name="apigateway-enable-cors-mock"></a>

これらの統合の場合、[CORS プロトコル](https://fetch.spec.whatwg.org/#http-cors-protocol)は、実際のリクエストを送信する前に、ブラウザからサーバーにプリフライトリクエストを送信し、サーバーからの承認 (または認証情報のリクエスト) を待つことを要求します。プリフライトリクエストに適切なレスポンスを送信するように API を設定する必要があります。

 プリフライトレスポンスを作成するには 

1. モック統合の `OPTIONS` メソッドを作成します。

1. 以下のレスポンスヘッダーを 200 メソッドレスポンスに追加します。
   + `Access-Control-Allow-Headers`
   + `Access-Control-Allow-Methods`
   + `Access-Control-Allow-Origin`

1. 統合パススルーの動作を `NEVER` に設定します。この場合、マッピングされていないコンテンツタイプのメソッドリクエストは、HTTP 415 Unsupported Media Type レスポンスで拒否されます。詳細については、「[API Gateway で REST API のマッピングテンプレートを使用しないペイロードのメソッドリクエストの動作](integration-passthrough-behaviors.md)」を参照してください。

1. レスポンスヘッダーの値を入力します。すべてのオリジン、すべてのメソッド、および共通のヘッダーを許可するには、以下のヘッダー値を使用します。
   + `Access-Control-Allow-Headers: 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'`
   + `Access-Control-Allow-Methods: 'DELETE,GET,HEAD,OPTIONS,PUT,POST,PATCH'`
   + `Access-Control-Allow-Origin: '*'`

プリフライトリクエストを作成したら、少なくとも 200 個すべてのレスポンスに対して、すべての CORS 対応メソッドの `Access-Control-Allow-Origin: '*'` ヘッダーまたは `Access-Control-Allow-Origin:{{'origin'}}` ヘッダーを返す必要があります。

### AWS マネジメントコンソールを使用して非プロキシ統合の CORS を有効にする
<a name="apigateway-enable-cors-mock-console"></a>

AWS マネジメントコンソールを使用して CORS を有効にすることができます。API Gateway は、`OPTIONS` メソッドを作成し、`Access-Control-Allow-Origin` ヘッダーを既存のメソッド統合レスポンスに追加します。これは常に機能するとは限りません。場合によっては、少なくとも 200 個すべてのレスポンスに対して、すべての CORS 対応メソッドの `Access-Control-Allow-Origin` ヘッダーを返すように統合レスポンスを手動で変更する必要があります。

API のバイナリメディアタイプが `*/*` に設定されている場合は、API Gateway が `OPTIONS` メソッドを作成するときに、`contentHandling` を `CONVERT_TO_TEXT` に変更します。

次の [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration.html) コマンドは、統合リクエストの `contentHandling` を `CONVERT_TO_TEXT` に変更します。

```
aws apigateway update-integration \
  --rest-api-id {{abc123}} \
  --resource-id {{aaa111}} \
  --http-method OPTIONS \
  --patch-operations op='replace',path='/contentHandling',value='CONVERT_TO_TEXT'
```

次の [update-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration-response.html) コマンドは、統合レスポンスの `contentHandling` を `CONVERT_TO_TEXT` に変更します。

```
aws apigateway update-integration-response \
  --rest-api-id {{abc123}} \
  --resource-id {{aaa111}} \
  --http-method OPTIONS \
  --status-code 200 \
  --patch-operations op='replace',path='/contentHandling',value='CONVERT_TO_TEXT'
```

## プロキシ統合の CORS サポートを有効にする
<a name="apigateway-enable-cors-proxy"></a>

Lambda プロキシ統合または HTTP プロキシ統合の場合、プロキシ統合は統合レスポンスを返さないため、バックエンドが `Access-Control-Allow-Origin` ヘッダー、`Access-Control-Allow-Methods` ヘッダー、`Access-Control-Allow-Headers` ヘッダーを返す必要があります。

以下の Lambda 関数の例は、必要な CORS ヘッダーを返します。

------
#### [ Node.js ]

```
export const handler = async (event) => {
    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Headers" : "{{Content-Type}}",
            "Access-Control-Allow-Origin": "{{https://www.example.com}}",
            "Access-Control-Allow-Methods": "{{OPTIONS,POST,GET}}"
        },
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};
```

------
#### [ Python 3 ]

```
import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'headers': {
            'Access-Control-Allow-Headers': '{{Content-Type}}',
            'Access-Control-Allow-Origin': '{{https://www.example.com}}',
            'Access-Control-Allow-Methods': '{{OPTIONS,POST,GET}}'
        },
        'body': json.dumps('Hello from Lambda!')
    }
```

------

**Topics**
+ [CORS サポートを有効にするかどうかを決定する](#apigateway-cors-request-types)
+ [シンプルなリクエストの CORS を有効にする](#apigateway-cors-simple-request)
+ [シンプルではないリクエストの CORS を有効にする](#apigateway-enable-cors-non-simple)
+ [プロキシ統合の CORS サポートを有効にする](#apigateway-enable-cors-proxy)
+ [API Gateway コンソールを使用してリソースで CORS を有効にする](how-to-cors-console.md)
+ [API Gateway のインポート API を使用して、リソースで CORS を有効にする](enable-cors-for-resource-using-swagger-importer-tool.md)
+ [API Gateway API の CORS をテストする](apigateway-test-cors.md)