

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

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

[跨來源資源共享 (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 請求可分為兩種類型：*簡單*請求和*非簡單*請求。

## 針對簡單請求啟用 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'` 標頭。

### 使用 為非代理整合啟用 CORS AWS 管理主控台
<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)

# 使用 API Gateway 主控台在資源上啟用 CORS
<a name="how-to-cors-console"></a>

您可以使用 API Gateway 主控台，為您已建立的 REST API 資源上的一個或所有方法啟用 CORS 支援。啟用 COR 支援後，將整合傳遞行為設定為 `NEVER`。在此案例中，未映射內容類型的方法請求會遭到拒絕，並顯示 HTTP 415 Unsupported Media Type (不支援的媒體類型) 回應。如需詳細資訊，請參閱[API Gateway 中 REST API 沒有映射範本時，承載的方法請求行為](integration-passthrough-behaviors.md)

**重要**  
資源可以包含子資源。對資源及其方法啟用 CORS 支援並不會對子資源及其方法遞迴啟用此支援。

**若要在 REST API 資源上啟用 CORS 支援**

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 選擇一個 API。

1. 在**資源**下，選擇一個資源。

1. 在**資源詳細資訊**區段中，選擇**啟用 CORS**。

      
![\[在資源窗格中，選擇啟用 CORS。\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/amazon-api-gateway-new-console-enable-cors.png)

1.  在**啟用 CORS** 方塊中，執行下列操作：

   1. (選用) 如果您已建立自訂閘道回應，並且想要針對回應啟用 CORS 支援，請選取閘道回應。

   1. 選取每一種方法以啟用 CORS 支援。`OPTION` 方法必須啟用 CORS。

      如果您為 `ANY` 方法啟用 CORS 支援，則所有方法的 CORS 都會啟用。

   1.  在 **Access-Control-Allow-Headers** 輸入欄位中，輸入逗號分隔標頭清單的靜態字串，用戶端必須在資源的實際請求中提交這些標頭。使用主控台提供的 `'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'` 標頭清單，或指定您自己的標頭。

   1. 使用主控台提供的 `'*'` 值以做為 **Access-Control-Allow-Origin** 標頭值，以允許所有來源中的存取請求，或指定允許其存取資源的起源。

   1. 選擇**儲存**。  
![\[選擇允許哪些標頭\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/amazon-api-gateway-new-console-enable-cors-resources.png)
**重要**  
 將上述說明應用在代理整合中的 `ANY` 方法時，不會設定任何適用的 CORS 標頭。反之，您的後端必須傳回適當的 CORS 標頭，例如 `Access-Control-Allow-Origin`。

在 `GET` 方法上啟用 CORS 之後，如果資源中尚未有 `OPTIONS` 方法，則系統會將此方法新增至資源。`OPTIONS` 方法的 `200` 回應會自動設定為傳回三個 `Access-Control-Allow-*` 標頭，來完成預檢交握。此外，根據預設也會設定實際 (`GET`) 方法，以在其 200 回應中傳回 `Access-Control-Allow-Origin` 標頭。對於其他類型的回應，如果您不想要傳回 `Cross-origin access` 錯誤，則需要使用 '\$1' 或特定來源手動進行設定，以傳回 `Access-Control-Allow-Origin'` 標頭。

在您的資源上啟用 CORS 支援之後，您必須部署或重新部署 API，新的設定才能生效。如需詳細資訊，請參閱[建立部署](set-up-deployments.md#create-deployment)。

**注意**  
如果您在遵循程序後無法在資源上啟用 CORS 支援，建議您比較 CORS 組態與範例 API `/pets` 資源。若要了解如何建立範例 API，請參閱 [教學課程：匯入範例來建立 REST API](api-gateway-create-api-from-example.md)。

# 使用 API Gateway 匯入 API 在資源上啟用 CORS
<a name="enable-cors-for-resource-using-swagger-importer-tool"></a>

如果您使用 [API Gateway 匯入 API](api-gateway-import-api.md)，即可透過 OpenAPI 檔案來設定 CORS 支援。您必須先在傳回必要標頭的資源中定義 `OPTIONS` 方法。

**注意**  
Web 瀏覽器必須在每個接受 CORS 請求的 API 方法中設定 Access-Control-Allow-Headers 與 Access-Control-Allow-Origin 標頭。此外，某些瀏覽器會先向相同資源中的 `OPTIONS` 方法提出 HTTP 請求，然後預期收到相同的標頭。

## 示例 `Options` 方法
<a name="enable-cors-for-resource-using-swagger-importer-tool-options"></a>

下列範例為模擬整合建立 `OPTIONS` 方法。

------
#### [ OpenAPI 3.0 ]

```
/users:
  options:
    summary: CORS support
    description: |
      Enable CORS by returning correct headers
    tags:
    - CORS
    responses:
      200:
        description: Default response for CORS method
        headers:
          Access-Control-Allow-Origin:
            schema:
              type: "string"
          Access-Control-Allow-Methods:
            schema:
              type: "string"
          Access-Control-Allow-Headers:
            schema:
              type: "string"
        content: {}
    x-amazon-apigateway-integration:
      type: mock
      requestTemplates:
        application/json: "{\"statusCode\": 200}"
      passthroughBehavior: "never"
      responses:
        default:
          statusCode: "200"
          responseParameters:
            method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
            method.response.header.Access-Control-Allow-Methods: "'*'"
            method.response.header.Access-Control-Allow-Origin: "'*'"
```

------
#### [ OpenAPI 2.0 ]

```
/users: 
   options:
      summary: CORS support
      description: |
        Enable CORS by returning correct headers
      consumes:
        - "application/json"
      produces:
        - "application/json"
      tags:
        - CORS
      x-amazon-apigateway-integration:
        type: mock
        requestTemplates: "{\"statusCode\": 200}"
        passthroughBehavior: "never"
        responses:
          "default":
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
              method.response.header.Access-Control-Allow-Methods : "'*'"
              method.response.header.Access-Control-Allow-Origin : "'*'"
      responses:
        200:
          description: Default response for CORS method
          headers:
            Access-Control-Allow-Headers:
              type: "string"
            Access-Control-Allow-Methods:
              type: "string"
            Access-Control-Allow-Origin:
              type: "string"
```

------

一旦您為資源設定 `OPTIONS` 方法，您就可以將必要的標頭新增至相同資源中需要接受 CORS 請求的其他方法。

1. 對回應類型宣告 **Access-Control-Allow-Origin** 與 **Headers**。

------
#### [ OpenAPI 3.0 ]

   ```
       responses:
         200:
           description: Default response for CORS method
           headers:
             Access-Control-Allow-Origin:
               schema:
                 type: "string"
             Access-Control-Allow-Methods:
               schema:
                 type: "string"
             Access-Control-Allow-Headers:
               schema:
                 type: "string"
           content: {}
   ```

------
#### [ OpenAPI 2.0 ]

   ```
       responses:
           200:
             description: Default response for CORS method
             headers:
               Access-Control-Allow-Headers:
                 type: "string"
               Access-Control-Allow-Methods:
                 type: "string"
               Access-Control-Allow-Origin:
                 type: "string"
   ```

------

1. 在 `x-amazon-apigateway-integration` 標籤中，將這些標頭的對應設定為您的靜態值：

------
#### [ OpenAPI 3.0 ]

   ```
       responses:
           default:
             statusCode: "200"
             responseParameters:
               method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
               method.response.header.Access-Control-Allow-Methods: "'*'"
               method.response.header.Access-Control-Allow-Origin: "'*'"
             responseTemplates:
               application/json: |
                 {}
   ```

------
#### [ OpenAPI 2.0 ]

   ```
       responses:
             "default":
               statusCode: "200"
               responseParameters:
                 method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
                 method.response.header.Access-Control-Allow-Methods : "'*'"
                 method.response.header.Access-Control-Allow-Origin : "'*'"
   ```

------

## API 範例
<a name="enable-cors-for-resource-using-swagger-importer-tool-complete-example"></a>

下列範例會建立具有 `HTTP` 整合 `OPTIONS` 方法和 `GET` 方法的完整 API。

------
#### [ OpenAPI 3.0 ]

```
openapi: "3.0.1"
info:
  title: "cors-api"
  description: "cors-api"
  version: "2024-01-16T18:36:01Z"
servers:
- url: "/{basePath}"
  variables:
    basePath:
      default: "/test"
paths:
  /:
    get:
      operationId: "GetPet"
      responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: "string"
          content: {}
      x-amazon-apigateway-integration:
        httpMethod: "GET"
        uri: "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets"
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Origin: "'*'"
        passthroughBehavior: "never"
        type: "http"
    options:
      responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: "string"
            Access-Control-Allow-Methods:
              schema:
                type: "string"
            Access-Control-Allow-Headers:
              schema:
                type: "string"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Empty"
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
        requestTemplates:
          application/json: "{\"statusCode\": 200}"
        passthroughBehavior: "never"
        type: "mock"
components:
  schemas:
    Empty:
      type: "object"
```

------
#### [  OpenAPI 2.0  ]

```
swagger: "2.0"
info:
  description: "cors-api"
  version: "2024-01-16T18:36:01Z"
  title: "cors-api"
basePath: "/test"
schemes:
- "https"
paths:
  /:
    get:
      operationId: "GetPet"
      produces:
      - "application/json"
      responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
      x-amazon-apigateway-integration:
        httpMethod: "GET"
        uri: "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets"
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Origin: "'*'"
        passthroughBehavior: "never"
        type: "http"
    options:
      consumes:
      - "application/json"
      produces:
      - "application/json"
      responses:
        "200":
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
            Access-Control-Allow-Methods:
              type: "string"
            Access-Control-Allow-Headers:
              type: "string"
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
        requestTemplates:
          application/json: "{\"statusCode\": 200}"
        passthroughBehavior: "never"
        type: "mock"
definitions:
  Empty:
    type: "object"
```

------

# 測試 API Gateway API 的 CORS
<a name="apigateway-test-cors"></a>

您可以透過叫用 API 來測試 API 的 CORS 組態，並在回應中檢查 CORS 標頭。下面的 `curl` 命令會傳送 OPTIONS 請求至已部署的 API。

```
curl -v -X OPTIONS https://{restapi_id}.execute-api.{region}.amazonaws.com/{stage_name}
```

```
< HTTP/1.1 200 OK
< Date: Tue, 19 May 2020 00:55:22 GMT
< Content-Type: application/json
< Content-Length: 0
< Connection: keep-alive
< x-amzn-RequestId: a1b2c3d4-5678-90ab-cdef-abc123
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token
< x-amz-apigw-id: Abcd=
< Access-Control-Allow-Methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
```

回應中的 `Access-Control-Allow-Origin`、`Access-Control-Allow-Headers` 和 `Access-Control-Allow-Methods` 標頭會顯示 API 支援 CORS。如需詳細資訊，請參閱[API Gateway 中 REST API 的 CORS](how-to-cors.md)。