Amazon API Gateway の AWS Service Proxy の使い方


Amazon API Gateway の Integration Type には、
1. Lambda Function
2. HTTP Proxy
3. AWS Service Proxy (Advanced)

の３つがある。
３つ目については、ドキュメントの[Walkthrough: API Gateway and an AWS Service Proxy](https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-aws-proxy.html) で触れられているが、パラメータを渡さずに ListTopics をするだけのサンプルとなり、正直あまり参考にならない。

SNS の Publish を例として、API にパラメータを与えるにはどうすればいいのかを検証した。

## POSTメソッドを作る
[先ほどのWalkThrough](https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-aws-proxy.html)でいう、[Step 2: Create the GET Method](https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-aws-proxy.html#getting-started-aws-proxy-add-methods)で、```2. For the HTTP method, choose GET, and then save your choice.```の代わりに、POSTメソッドを作成する。

[Step 4: Specify Method Settings and Test the Method](https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-aws-proxy.html#getting-started-aws-proxy-set-methods)の ``` 6. For Action, type ListTopics. ``` の代わりに、Publish としておく。

![screenshot](http://g.s3w.jp/aa3f0e1a)

とりあえず Save して Test を押すと

```json
{
  "Error": {
    "Code": "InvalidParameter",
    "Message": "Invalid parameter: TopicArn or TargetArn Reason: no value for required parameter",
    "Type": "Sender"
  },
  "RequestId": "d2612a98-55d9-50ae-989d-64a2a1812b1c"
}
```

というエラーになる(まぁそうでしょう、TopicArnは必須パラメータですし)。

## パラメータを足す
ログを見てみると、
> Endpoint request URI: https://sns.us-west-2.amazonaws.com/?Action=Publish

と、QueryStringでパラメータを渡しているようなので、TopicArnとMessageを与えられるようにしてみる。

まず入力部分の MethodRequest の URL Query String Parameters に topicArn と message を足す。
![screenshot](http://g.s3w.jp/aa3f0d14)

次にAPIコールをする設定 Integration Request の URL Query String Parameters に、 TopicArn と Message を足す。
![screenshot](http://g.s3w.jp/aa3f0bf9)

## テスト

再度 Test 画面に行き、Query String の message と topicArn を入力 (Request Bodyは空)、Testボタンを押す。
![screenshot](http://g.s3w.jp/aa3f0bb1)

すると、

```json
{
  "PublishResponse": {
    "PublishResult": {
      "MessageId": "44c1e791-6722-5dca-a4c1-a9ab91bbd63e"
    },
    "ResponseMetadata": {
      "RequestId": "c2f22e0a-04c7-51fc-be50-6030f25eca08"
    }
  }
}
```

のようなレスポンスが返り、SNSメッセージがPublishされた。

Deployして、curlでも確かめる。

```
$ curl -X POST 'https://xxxxxxxx.execute-api.us-west-2.amazonaws.com/dev/mydemoawsproxy?topicArn=arn:aws:sns:us-west-2:123456789012:apigw&message=HelloFromCurl'
{"PublishResponse":{"PublishResult":{"MessageId":"83f40b1c-82a6-550e-a542-4526758fc6a0"},"ResponseMetadata":{"RequestId":"d92f2d00-a890-5612-85a4-633a5fb9a5bc"}}}
```

無事にPublishする事が出来た。

ちなみにスペースを入れるときは、３回エスケープしなくてはいけないようで、スペース１つが %252520 (-> %2520 -> %20 -> ' ') となる。

```
$ curl -X POST 'https://xxxxxxxx.execute-api.us-west-2.amazonaws.com/dev/mydemoawsproxy?topicArn=arn:aws:sns:us-west-2:123456789012:apigw&message=Hello%252520From%252520Curl'
```

## QueryString じゃなくて Request Body で渡したい？
AWS CLIだと、下記のようなJSON を Request Body として / にPOSTしているようなので、同じようにやりたい。

```{'Action': u'Publish', u'Message': u'Hello from AWS CLI', 'Version': u'2010-03-31', u'TopicArn': u'arn:aws:sns:us-west-2:123456789012:apigw'}```

ところが Integration Request の Action Type が Use action name だと Action 以外のパラメータをJSONに入れて Request Bodyに入れて送っても無視されてしまう。
そこで Use path override にして、Path override を / にすると、

> Endpoint request URI: https://sns.us-west-2.amazonaws.com//

に POST しようとしてしまう。

Path override を ? にすると
> Endpoint request URI: https://sns.us-west-2.amazonaws.com/?

に POST できるが、Signatureがミスマッチとなる。

Path override を空欄にすると
> Endpoint request URI: https://sns.us-west-2.amazonaws.com/null

に POST しようとしてしまう。

つまり、 / にPOSTする事が出来ない ＞＜
どうすればいいんでしょうかね...コレ。

Path override を空欄にしたときに https://sns.us-west-2.amazonaws.com/ にPOST出来ればよいのですが。