Tips: API Gatewayのエクスポート／インポートでハマったところ

AWSコンソールからAPI Gatewayの設定をいじってたんですが、何を変更したかわからなくなったり、変更した差分が欲しかったりしたのでswagger用のファイルで管理することにしました。
ツールもあるのですんなり出来るかと思いましたが、いくつかハマった部分があるので残しときます。

# Export

AWSコンソールから行えます。
エクスポートしたいAPIのStageを選択し、右にある``Export``タブからYAML / JSONがダウンロードできます。

<img width="1543" alt="API_Gateway.png" src="https://qiita-image-store.s3.amazonaws.com/0/20274/85c1a6bd-1c38-35a5-f6d4-75d47c8fda38.png">


なおエクスポートされるのはそのStageで使用しているリソースやモデルのみで、例えばErrorやEmptyといったデフォルトで用意されているAPI Gatewayのモデルも使ってなければエクスポートしたファイルには含まれません。

## Export as Swagger

swaggerの定義ファイルのみ。
これをインポートしてもリソース定義のみでAPI Gateway独自の認証や呼び出すLambda Functionなどの設定はされません。

## Export as Swagger + API Gateway Extentions

上記に加えAPI Gateway用の設定もエクスポートされます。
各リソースの設定などを含んでますので後述する``aws-apigateway-importer``でインポートするならこれでエクスポートしたファイルを使うのが良さそうです。

## Export as Swagger + Postman Extentions

[Postman](http://www.getpostman.com/)用の設定が追加？
見たところPostmanでテストするのに必要なリクエストヘッダが追加されてるようです。
[Chrome Extension版](https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop)はデバッグ時などによく使いますね。

# Import

こちらのツールを使います。
https://github.com/awslabs/aws-apigateway-importer

使い方はクラスメソッドさんの記事がわかりやすいです。
http://dev.classmethod.jp/cloud/api-gateway-swagger-importer/

なお以降の記事は以下の実行環境で試してます。

* aws-apigateway-importer  
``commit 626a9c98cf05dbd040f6a87e978b9edf71d7209d``
* java  
homebrewでインストールした ``java version "1.8.0_66"``

## ハマった部分

### ビルド時に``javac: 1.8は無効なターゲット・リリースです``のエラー

* エラーメッセージ

```
[ERROR] Failure executing javac, but could not parse the error:
javac: 1.8は無効なターゲット・リリースです
使用方法: javac <options> <source files>
使用可能なオプションのリストについては、-helpを使用します
```

* 原因  
java 1.7だとダメみたいです。  
homebrewで1.8に更新したら無事ビルド成功しました。

### ``Auth type is required``のエラー

* エラーメッセージ

```
2015-12-24 15:58:26,839 ERROR - Error creating API, rolling back
com.amazonaws.services.apigateway.model.BadRequestException: AWS_IAM Auth type is required for AWS integrations with identity forwarding specified (Service: null; Status Code: 400; Error Code: null; Request ID: xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx)
```

* 原因
githubのREADME.mdに記載がありますが、各リソースに``x-amazon-apigateway-auth``の定義がないことが原因です。
``x-amazon-apigateway-integration``と同じ階層に追加してあげればOK。

```yaml:swagger.yaml
      x-amazon-apigateway-auth:
        type: "aws_iam"
      x-amazon-apigateway-integration:
```

### ``Invalid mapping expression``のエラー

* エラーメッセージ

```
2015-12-24 15:49:42,674 ERROR - Error creating API, rolling back
com.amazonaws.services.apigateway.model.BadRequestException: Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression parameter specified: method.response.header.Access-Control-Allow-Methods] (Service: null; Status Code: 400; Error Code: null; Request ID: xxxxxx-xxxx-xxxx-xxxxxxxxxx)
```

* 原因  
API GatewayでCORSリクエストを許可するためレスポンスヘッダの設定を入れてたんですが、それがインポート時にうまく処理されてないみたい？  
※CORSの設定は公式ドキュメントより補足のあるクラスメソッドさんの記事がわかりやすいです。  
（参考：[Amazon API Gateway をクロスオリジンで呼び出す (CORS)](http://dev.classmethod.jp/cloud/aws/amazon-api-gateway-cors/)）  
さらに、この時はCORSは不要になったのでAWSコンソールからヘッダ設定を削除したんですが、エクスポートしたファイルにはなぜかヘッダが残っている状態。  
結局swaggerファイルから直接以下の行を削除してインポートしたらうまくいきました。

```yaml:swagger.yaml
            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: "'*'"

```
追記：
これは``Integration Response``の``Header Mappings``から該当ヘッダを削除する前に、``Method Response``のヘッダを削除してしまったために発生していた現象でした。
エクスポートしたファイルにヘッダの定義はないのにintegration側にヘッダ設定が残っていて不整合が起きてたのが原因でした。
ヘッダを削除するときには先にマッピングしてる方から削除しましょう。
ヘッダがちゃんと定義されてる状態だとインポートもうまくいきました。

### モデルの2階層目の``properties``が消えている

こんな感じで定義してたモデルが、

```json
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "user": {
      "type": "object",
      "properties": {
        "userId": {
          "type": "string"
        },
        "userName": {
          "type": "string"
        }
      }
    }
  }
}
```
インポートするとこんな感じになります。

```json
{
  "definitions": {},
  "type": "object",
  "properties": {
    "user": {
      "type": "object"
    }
  }
}
```
要するに2階層目の``propeties``がインポートされてない（エクスポートされたファイルには入っている）。
[API Gatewayのドキュメント](https://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings.html)を見る限りだと2階層の定義もされてるんですが、これはJSON SchemaのルールだとNGなのかも？
未解決なので時間とってちゃんと調べたい。

### パスの最上階層に``/{stage-name}``が入っている

* 原因  
これはAPI Gatewayからエクスポートするとswaggerの``basePath``パラメータにStage名が入ってるんですが、インポートの際にはこれをAPIの基底パスとして認識するため発生してます。  
Stage名が不要な場合は以下のようにエクスポートしたswaggerの``basePath``を変更しましょう。

```yaml:swagger.yaml
basePath: "/prod"
↓
basePath: "/"
```