Amazon Product Advertising API を使った書籍検索 API をサクッと作る

Amazon Product Advertising API を使って、本の ISBN コードを GET すると、
書籍情報を返してくれる API を JavaScript で作り Now(v2)にデプロイしました。

## Amazon Product Advertising API の準備

Amazon Product Advertising API は登録しないと使えないので、登録を行って、

- [アソシエイトタグ](https://affiliate.amazon.co.jp/)
- [アクセスキー](https://affiliate.amazon.co.jp/gp/advertising/api/detail/main.html)
- [シークレットキー](https://affiliate.amazon.co.jp/gp/advertising/api/detail/main.html)

を取得しておきます。

## JavsScript のコード

Amazon Product Advertising API を使うためのライブラリで、
今回は[node-apac](https://github.com/dmcquay/node-apac)を使いました。
あとは、express で簡易的な API サーバを立てて、ISBN コードが GET されたら、
それを元に API に投げて、書籍情報を返却するようにしています。
以下がコードになります。

```JavaScript
const express = require('express');
const bodyParser = require('body-parser');

const app = express();

const { check, validationResult } = require('express-validator/check');
const { matchedData } = require('express-validator/filter');
const { OperationHelper } = require('apac');

const opHelper = new OperationHelper({
  awsId: process.env.AWSID, //アクセスキー
  awsSecret: process.env.AWSSECRET, //シークレットキー
  assocId: process.env.ASSOCID, //アソシエイトタグ
  locale: 'JP'
});

app.use(bodyParser.urlencoded({ extended: true }));

app.get('/', [check('isbn').exists()], async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty())
    return res.status(422).json({ errors: errors.mapped() });

  const valid = matchedData(req);
  const isbnCode = valid.isbn;

  opHelper
    .execute('ItemLookup', {
      SearchIndex: 'Books',
      IdType: 'ISBN',
      ItemId: isbnCode,
      ResponseGroup: 'ItemAttributes,Images'
    })
    .then(response => {
      let responseItem = null;

      if (!response.result.ItemLookupResponse.Items.Item['0']) {
        responseItem = response.result.ItemLookupResponse.Items.Item;
      } else {
        responseItem = response.result.ItemLookupResponse.Items.Item['0'];
      }

      const bookData = {
        title: responseItem.ItemAttributes.Title,
        author: responseItem.ItemAttributes.Author,
        publisher: responseItem.ItemAttributes.Publisher,
        releaseDate: responseItem.ItemAttributes.ReleaseDate,
        imageURL: responseItem.LargeImage.URL
      };

      res.json({
        bookData
      });
    })
    .catch(err => {
      res.status(422).json({ errors: '存在しません。' });
    });
});

app.listen(3000, () => console.log('Example app listening on port 3000!'));

module.exports.app = app;
```

## Now にデプロイ

Now をインストールしていない人は、`npm i -g now`でインストールを行って、登録をしてください。

### Now の準備

Now にデプロイする前に準備をします。

#### now.json

まずは、`now.json`を作成します。
`version`は`2`で、`name`、`alias`は個別の名前を設定してください。
`alias`はなくてもいいのですが、Now の場合デプロイ毎に URL が変わってしまうので、
API として使う場合は設定しておいたほうがいいと思われます。

`env`は環境変数として設定しているアクセスキーなどを Now で使うための設定になります。
後述する`now secrets`の設定で連携させます。

```json
{
  "version": 2,
  "name": "APIの名前",
  "alias": "APIの固定URL",
  "env": {
    "AWSID": "@awsid",
    "AWSSECRET": "@awssecret",
    "ASSOCID": "@associd"
  },
  "builds": [{ "src": "index.js", "use": "@now/node-server" }]
}
```

#### .nowignore ファイルの作成

Now のコードは全て見えちゃうので、(URL に`/_src`をつけると見える)
Now にあげたくないファイルを`.nowignore`ファイルに記述します
ここでは、`direnv`を使ってるので、`.envrc`ファイルを対象にしています。

```.nowignore
.envrc
```

#### now secrets の実行

環境変数を Now で使えるようにするために以下のコマンドを実行します。
設定した`secrets`は`now.json`と連携するように記述します。

```zsh
now secrets add awsid 'アクセスキー'
now secrets add awssecret 'シークレットコード'
now secrets add associd 'アソシエイトタグ'
```

設定できたか確認する場合は、以下のコマンドを実行することで確認できます。

```zsh
$ now secret ls

> 3 secrets found under takutakuma [582ms]

  name       created
  awsid      3d ago
  awssecret  3d ago
  associd    3d ago

```

### Now にデプロイ

ここまで準備できたら、 Now にデプロイしましょう。
以下のコマンドを実行すると Now にデプロイができているので、
API として動くか確認してください。

```zsh
now
now alias
```

## その他

- 書籍の情報検索 API は色々あるのですが、どれも一長一短でなかなか選定が難しかったです。
- ISBN での検索だと Amazon API は Kindle 本を除外できない仕様みたいです。