API Gateway + Lambda で固定のパラメータを付加して HTTP Proxy する

API Gateway による HTTP Proxy は作例がたくさんある (というかコンソールぽちぽちするだけで作れる) のだけど、endpoint 側に Query String を渡す際に、client から渡ってきていないパラメータを追加しようとすると素直にはいかなかったのでメモ。

やりたかったこと

  1. 下図の (a) で zipcode=hoge が渡ってくる
  2. (b) で zipcode=hogezn=hoge にした上で、
  3. 更に ver=0 というパラメータを追加したい

            | --(a)-> |         | --(b)-> |
     Client |         |   API   |         | GET
            |         | Gateway |         | http://exmaple.com/api/
            | <------ |         | <------ |
    

どうすればいいのか

Lambda で HTTP Proxy 的な処理を書いて GET させるとよい。


詳細は以下のとおりです。 なお、記事にするにあたり 郵便番号検索API を利用させて頂きました。

Integration type: HTTP Proxy だとダメ

Integration type: HTTP Proxy にすると、client から渡ってきた Query String を endpoint に渡す 際、key は変更できるものの、value を変えたり、特定の key を静的に(=固定で)指定といったことはできないようです。

よって、"更にパラメータを追加" するには他の手段をとる必要がありそうです。

Lambda を使う

やや面倒ではあるものの、API Gateway に用意されている HTTP proxy ではなく、Lambda を経由して GET させてみました。

以下は Lambda のコードです。

var request = require('request');
exports.handler = function(event, context) {
    // endpoint 側に渡すパラメータ
    // event には Mapping Template に記述した内容が渡ってくる
    var params = { zn:event.zipcode, ver:'0' }; 

    // コンテンツをパラメータ付きで get
    request.get({url:"http://zip.cgis.biz/xml/zip.php", qs: params}, function(err, res, body) {
      if (!err && res.statusCode == 200) {
        context.done(null, body);
      } else {
        console.log('error: '+ res.statusCode);
      }
    });
};

request モジュールを要求するため、AWSへは node_modules を含む zip ファイルとしてアップロードします。

npm install request
zip -r zipcode.zip index.js node_modules

API Gateway の設定

(APIやResourcesの作成などの基本的な設定は省略します。)

Method Execution には以下の2つの設定を行います。

  1. Method Request の URL Query String Parameters に受け取るパラメータを追加
    • zipcode f:id:chrolis:20151117180401p:plain
  2. Integration Request に Mapping Templates を設定
    • Content-Type: application/json
    • { "zipcode": $input.params("zipcode") }
      ( ちなみにシングルクオートだと上手くいかなかった )
      f:id:chrolis:20151117180410p:plain

上記の例に従った場合、Method Test の結果がこんな感じになれば成功しています。

f:id:chrolis:20151117180429p:plain