Amazon PA-API(Product Advertising API) を golang から呼び出してみようと思った。

構成としては、フォームを一枚置いて、アプリサーバーで Amazon PA-API を実行するという構成だ。PHP で簡単にできそうな気もするが、golang の勉強もかねてこの構成とした。

さて、アプリサーバーを置かないといけないのだが、できればクラウドの無料枠を使いたい。Google App Engine あたりが適当なのではないかと考えた。サンプルを見たところ、golang で作った http サーバがそのまま Google App Engine にデプロイできるので、とても簡単だ。

golang で PA-API を呼び出すフリーのライブラリもあるのだが、無料枠が使えるスタンダード環境の golang バージョンでは使えなかった。そこで、net/http と aws 提供の SDK を使って呼び出してみることにした。

リクエストの送信は json を POST すればよいだけなので特にはまりどころは無い。少し考えないといけないのは、Authorization Header の生成だ。送信方法自体は、Sending a Requestに書いてある。Authorization Header の生成は、java サンプルにあるように実装してもよいのだが、aws が提供している aws-sdk-go の signer/v4 を使うことができる。(gist にコードの一部分を置いた。) aws-sdk-go は Google App Engine のスタンダード環境でも使えた。

試してみたところでは、

  • content-type
  • content-encoding
  • x-amz-target

のヘッダを作って、signer の Sign 関数を呼べば、認証は通って、応答が得られた。内部的に生成される、host ヘッダを付けて Sign 関数を呼ぶと、エラーになった。(Authorization ヘッダ内の SignedHeader に複数の host が現れる) 無関係なヘッダを付けていると、そのヘッダも署名されるようだが、付いていても問題なさそうだった。

signer/v4 の使い方は、https://github.com/aws/aws-sdk-go/blob/main/aws/signer/v4/v4_test.go の testSignRequest 関数が参考になる。

Sign 関数に body パラメータを渡す必要があり、渡した body が付加される。(body パラメータに対するシグネチャー生成のためか?)http.NewRequest 時に渡したものと同じものを渡してもよいのだが、もし、Authorization ヘッダを付ける機能を関数化する場合、NewRequest で渡したものをもう一度渡すのもソフトウェアの整合性としてどうなのか、と思った。そういうわけで、一旦、ReadAll して、bytes.NewReader する実装としてみた。

あとは、このアプリサーバーにリクエストを送るフォームを設置する。

これで、PA-API を呼び出すアプリを作ることができた。

See Also