概要
2016年11月にAPI GatewayでBinaryデータが扱えるようになりました。
Binary Data Now Supported by API Gateway
Claudia.jsのAPI Builderでも対応していたため、試しにClaudia.jsでS3に置いた画像ファイルをAPI経由でダウンロードできるようにしてみたいと思います。
コード
まずAPIBuilderの設定で、どのMIME-TYPEをバイナリとして扱うかを指定する必要があります。これはsetBinaryMediaTypes
で行います。
import ApiBuilder from 'claudia-api-builder'
const api = new ApiBuilder()
api.setBinaryMediaTypes(['image/jpeg', 'image/jpg', 'image/png'])
各APIリソースの設定では、レスポンスのオプションでcontentHandling: ''CONVERT_TO_BINARY''
を指定する必要があります。このオプションを指定することにより、APIGatewayでbase64エンコーディングされた文字列がバイナリデータに変換されます。
api.get('/img', requestHandler, {
success: {
contentHandling: 'CONVERT_TO_BINARY',
},
})
リクエストハンドラーの処理は以下のようになります。
const requestHandler = async () => {
const params = {
Bucket: 'bucketName',
Key: 'images/sample01.jpg',
}
const data = await this.s3.getObject(params).promise()
const response = new api.ApiResponse(data.Body, {
'Content-Type': data.ContentType,
}, 200)
return response
}
動的にS3データのContent-Typeをレスポンスヘッダに指定しています。動的にResponseを返す場合はapi.ApiResponse
のインスタンスを返す必要があります。
responseのbodyは、base64に変換しなくてもBufferのまま返せばClaudia.jsのAPIBuilderが自動でbase64に変換してくれます。
検証
この状態でデプロイし、テストしてみます。事前にS3のバケットを用意して適当な場所(images/sample01.jpg
等)に画像ファイルを配置しておきます。
HTTPリクエストは以下のようにAccept
ヘッダを指定する必要があります。
curl -H "Accept: image/jpg" "https://<id>.execute-api.ap-northeast-1.amazonaws.com/latest/img" > /tmp/image.jpg
ダウンロードしたファイルをビューワー等で問題なく開くことができればOKです。
問題
画像がダウンロードできるようになったのでWebページのHTMLの<img>
タグのsrcに指定して利用したいところですが、問題があります。Accept
ヘッダに複数のMIME-TYPE("image/*"
や、"image/png, image/jpg"
等)を指定した場合、画像が正常にダウンロードできません。Claudia.jsのドキュメントにも以下のように書かれていますが、Accept
ヘッダを複数指定した場合変換がうまく動作しないようです。
Similarly, although the documentation suggests that multiple content types can be specified in the Accept header for binary responses, it seems that this breaks the conversion. This makes the current implementation useless for browsers, which by default request complex Accept headers. This means that it’s currently not possible to use the API Gateway/AWS_PROXY integration to return images that can be just included into a web page using the img tag.
ブラウザのデフォルトの動作として、imgタグのHTTPリクエストではデフォルトでAcceptヘッダを複数指定するため、正常に画像を取得することができません。つまり、現状では<img>
タグからは利用できないということになります。
終わりに
現状では<img>
タグからは利用できませんが、こちらの問題がクリアされれば、Webページの画像APIとしてバリバリ利用できそうな気がします。
※サンプルコードはGithubに上げてます (https://github.com/gaishimo/claudiajs-image-downloader)