LoginSignup
11
16

More than 5 years have passed since last update.

Amazon API GatewayにバイナリデータがPOSTできない

Last updated at Posted at 2016-05-27

結論

2016/11/17 API GatewayでBinaryデータの送受信がサポートされましたので、このエントリーは無効となりました。よかったね!

Amazon API Gatewayは Content-Type: application/octet-stream なデータをPOSTで受信しても、無意味なデータができあがってしまいます
この件、ドキュメントには書いてないようです。。。

※gzipなデータを送りたければ Content-Encoding: gzip ヘッダをつければ大丈夫です

概要

Forumにも書かれているとおり、Amazon API GatewayはPOSTされたpayloadに対してUTF-8変換を行うようです
この時non-ASCIIなbyteは 0xEF 0xBF 0xBD に変換されてしまうため、POST元のpayloadデータと一致しない、改変されたデータが作られることになります

そしてIntegrated Requestにおいては $input.body は、改変後データが格納されており、オリジナルを取得する方法が見つかりません

検証方法

  1. Amazon API Gatewayで受けたPOSTをS3(bucket: apigw-testing)に保存するようにセットアップ
  2. 下記 target.json をそれぞれの形式で圧縮
  3. curlを使って検証

Amazon API Gatewayのセットアップ

基本的にはチュートリアルに沿って作ります

下記はオリジナルです(設定方法は割愛で)

  • POST https://APIGATEWAY/STAGE/{type} でS3に保存されるオブジェクト名をコントロールできるようにしています

あと、セットアップ中のテストではAPI GatewayのHTTP ProxyでTestでのみエラーが発生するといった罠が現在あるようですので、バケットを作るリージョンはお気をつけて

検証

$ convert -size 1x1 xc:#990000 original.gif
$ curl -H "Content-Type: application/octet-stream" --data-binary @original.gif -X POST https://${APIGATEWAY}.execute-api.ap-northeast-1.amazonaws.com/prod/apigw.gif
$ aws s3api get-object --bucket apigw-testing --key apigw.gif apigw.gif
{
    "AcceptRanges": "bytes",
    "ContentType": "application/octet-stream",
    "LastModified": "Fri, 27 May 2016 00:53:14 GMT",
    "ContentLength": 53,
    "ETag": "\"7276f51bcbfb892c6ba28a54af1842fc\"",
    "Metadata": {}
}

確認

$ wc -c original.gif apigw.gif
43 original.gif
53 apigw.gif
$ od -tx1z original.gif
0000000 47 49 46 38 39 61 01 00 01 00 f0 01 00 00 00 00  >GIF89a..........<
0000020 ff ff ff 21 f9 04 00 00 00 00 00 2c 00 00 00 00  >...!.......,....<
0000040 01 00 01 00 00 02 02 44 01 00 3b                 >.......D..;<
0000053
$ od -tx1z apigw.gif
0000000 47 49 46 38 39 61 01 00 01 00 ef bf bd 01 00 00  >GIF89a..........<
0000020 00 00 ef bf bd ef bf bd ef bf bd 21 ef bf bd 04  >...........!....<
0000040 00 00 00 00 00 2c 00 00 00 00 01 00 01 00 00 02  >.....,..........<
0000060 02 44 01 00 3b                                   >.D..;<
0000065

0xF0 や 0xFF が 0xEF 0xBF 0xBD に変換されている(そのためサイズも変更されてる)

どうしてもバイナリを送りたい

現時点では、直接Amazon API Gatewayでバイナリを取り扱うことはできませんでしたが、送信側でBase64 encodingができるなら、まだ道はあります

Integration Requestで $util.base64Decode() を使えば、受け取ったBase64edな文字列をdecodeしたあとのバイナリデータで後続のサービスに引き渡すことができます

$util変数へのアクセス

あとがき

ま、RESTな環境でnon-ASCIIなデータを送るってのもレアケースですよね

11
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
16