API Gatewayにインポートするswaggerファイルのtips

## はじめに

API Gatewayにはswaggerファイルをインポートしてリソースを作成する方法があります。
その時に、API Gatewayに合わせた特殊な書き方がいくつかあったので共有しておきます。
前提として、CDKでリソースを構築する際に気を付けることを挙げています。

API Gateway+CDK+swaggerみたいな話は以下の記事を参考にしてください。
実際に、僕はCDKを使ってリソース構築したかったのでとてもお世話になりました。

https://dev.classmethod.jp/articles/aws-cdk-apigateway-swagger-koneta/

https://zenn.dev/taroman_zenn/articles/91879cec40627c


### CORS有効化について

APIを作成するときにCORSの設定をすることがあります。
マネージコンソール上からならボタン１つで簡単にできますが、実際のAPIではURIがたくさんあり全てに対して「CORS有効にする」のボタンを押すのは大変です。

![スクリーンショット 2023-12-17 21.37.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3218510/01861bdb-ceb2-6dcc-9e45-6045f63a1586.png)


そこでswaggerファイルで以下のように記述しておくと、「CORS有効化」で追加される設定を最初から設定しておけます。
- 各CRUDメソッドのレスポンスに`'#/components/responses/normal'`を追加する
- 各リソース(URL)に`options`メソッドを追加する
    - `options`メソッドの内容も記述の通り


```yaml:openapi.yaml
paths:
  '/shops/{Id}':
    get:
      tags:
        - shop
      operationId: getShopById
      summary: 指定した店舗の詳細
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '200':
          $ref: '#/components/responses/normal'
    put:
      tags:
        - shop
      operationId: updateShop
      summary: 指定した店舗の情報更新
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '200':
          $ref: '#/components/responses/normal'
    delete:
      tags:
        - shop
      operationId: deleteShop
      summary: 指定した店舗の削除
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '200':
          $ref: '#/components/responses/normal'
    options:
      responses:
        '200':
          $ref: '#/components/responses/options_normal'
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: '200'
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: '''GET,OPTIONS,POST,DELETE,PUT'''
              method.response.header.Access-Control-Allow-Headers: '''*'''
              method.response.header.Access-Control-Allow-Origin: '''*'''
        requestTemplates:
          application/json: '{"statusCode": 200}'
        passthroughBehavior: when_no_match
        type: mock
components:
  schemas:
    Empty:
      title: "Empty Schema"
      type: "object"
  responses:
    normal:
      description: 取得成功
      headers:
        Access-Control-Allow-Origin:
          schema:
            type: "string"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Empty"
    options_normal:
      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"
  parameters:
    id:
      - name: "Id"
        in: "path"
        required: true
        schema:
          type: "string
```

### メディアタイプについて

API Gatewayではバイナリメディアタイプを設定できますが、これもswaggerファイルに書いておくことができます。

![スクリーンショット 2023-12-17 21.55.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3218510/9664b44d-45fe-e390-1c8e-24044016cf7f.png)

```yaml:openapi.yaml
paths:
  '/shops/{Id}':
    get:
      tags:
        - shop
      operationId: getShopById
      summary: 指定した店舗の詳細
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '200':
          $ref: '#/components/responses/normal'
    put:
      tags:
        - shop
      operationId: updateShop
      summary: 指定した店舗の情報更新
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '200':
          $ref: '#/components/responses/normal'
components:
  schemas:
    ...
  responses:
    ...
  parameters:
    ...

# 最後にこれを追加する
x-amazon-apigateway-binary-media-types:
  - multipart/form-data
```

### API認証

API Gatewayではcognito認証やAPIキーによる認証など可能で、swaggerで設定を書くと以下の通りです。
各メソッドに`security`プロパティを追加して、`components/securitySchemes`で定義している変数名を指定する

```yaml:openapi.yaml
paths:
  '/shops/{Id}':
    get:
      tags:
        - shop
      operationId: getShopById
      summary: 指定した店舗の詳細
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '200':
          $ref: '#/components/responses/normal'
      security:
          - CognitoAuth: []
    put:
      tags:
        - shop
      operationId: updateShop
      summary: 指定した店舗の情報更新
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '200':
          $ref: '#/components/responses/normal'
      security:
          - ApiKeyAuth: []
components:
  securitySchemes:
    # cognitoのユーザープール認証の設定
    CognitoAuth:
      type: apiKey
      name: Authorization
      in: header
      x-amazon-apigateway-authtype: cognito_user_pools
      x-amazon-apigateway-authorizer:
        type: cognito_user_pools
    # APIキーの設定
    ApiKeyAuth:
      type: apiKey
      name: x-api-key
      in: header
  schemas:
    ...
  responses:
    ...
  parameters:
    ...
```