0
0

【API Gateway】バイナリペイロードを適切に扱う

Posted at

はじめに

API Gatewayで扱うリクエスト、レスポンスに含まれるペイロードはテキストペイロードとバイナリペイロードに区分される。

ペイロード 説明
テキスト UTF-8エンコードされた JSON 文字列
バイナリ テキストペイロード以外のペイロード

image.png
バイナリペイロードを扱うためには、Lambdaプロキシ統合の利用有無によって適切にAPI Gatewayを構成する必要がある。

Lambdaプロキシを利用する場合

必要な設定は以下の通りです。

  • レスポンスのbase64エンコード
    Lambdaプロキシの利用時にバイナリペイロードを処理するためには、Lambdaからのレスポンスをbase64でエンコードする必要がある。

  • binaryMediaTypes
    binaryMediaTypesbinaryを設定し、APIがバイナリデータとして扱うコンテンツタイプを定義する必要がある。

    バイナリメディアタイプ例 説明
    image/jpeg JPEG画像
    image/png PNG画像
    application/pdf PDFドキュメント
    audio/mpeg MP3音声ファイル
    video/mp4 MP4動画ファイル
    text/csv CSV
    application/msword Word
    application/gzip GZip
    application/json JSON
    application/vnd.ms-powerpoint PowerPoint
    application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Excel(.xlsx)
    application/vnd.ms-excel Excel(.xls)
    application/zip ZIP
    application/octet-stream 任意のバイナリデータ
    */* すべてのコンテンツタイプ

S3のデータを取得する例

image.png

  • IAMロールを以下の通り作成
    image.png

  • LambdaをNode.jsで作成
    IAMロールは先程作成したものを割り当てる。
    Excelを返却する際のコードは以下の通り。

import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3"

const client = new S3Client({region: 'ap-northeast-1'});

export const handler = async (event) => {
  const bucket = event.path.split('/')[2]
  const key = event.path.split('/')[3]
  const input = {
    "Bucket" : bucket,
    "Key" : key
    }
  try {
    const command = new GetObjectCommand(input)
    const response = await client.send(command);
    var str = await response.Body.transformToByteArray();
  } catch (err) {
    console.error(err);
  }
  const base64body = Buffer.from(str).toString('base64');
  return {
    'headers': { "Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" },
    'statusCode': 200,
    'body': base64body,
    'isBase64Encoded': true
    }
}
  • API Gatewayを作成

    • リソースを以下の通り作成
      image.png

    • {item}リクエストにGETメソッドを以下の通り作成
      作成したLambdaのARNを指定する
      image.png
      image.png

    • バイナリサポートの有効化

      • APIの設定
        • 「メディアタイプを管理」を押下
          image.png
        • ダウンロード対象のデータに対応するバイナリメディアタイプを指定して保存。
          エクセル(.exls)を扱う場合は以下の通りに指定。
          application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
          
          image.png
  • 動作確認
    POSTMANにてAPIへのGETリクエストを行い、S3のファイルをダウンロードできることを確認する。

    image.png

Lambdaプロキシを利用しない場合

  • RestApiリソースのbinaryMediaTypesリストにメディアタイプを追加
  • IntegrationおよびIntegrationResponseリソースのcontentHandlingプロパティを設定することもでる
    • contentHandlingの値は、CONVERT_TO_BINARY、CONVERT_TO_TEXT、またはundefinedを指定する
    • contentHandlingの値と、レスポンスのContent-Typeヘッダーまたは受信リクエストのAcceptヘッダーがbinaryMediaTypesリストのエントリと一致するかどうかに応じて、API Gatewayは生のバイナリをbase64エンコード文字列としてエンコードしたり、base64エンコード文字列を生のバイトにデコードしたり、本文を変更せずに渡したりすことができる

S3のデータを取得する例

image.png

  • メソッド実行に用いるIAMロールを以下の通り作成
    image.png

  • API Gateway の作成

    • リソースを以下の通り作成
      image.png

    • {item}リクエストにGETメソッドを以下の通り作成
      実行ロールは先程作成したIAMロールを指定する
      image.png
      image.png

    • バイナリサポートの有効化

      • APIの設定

        • 「メディアタイプを管理」を押下
          image.png
        • ダウンロード対象のデータに対応するバイナリメディアタイプを指定して保存。
          エクセル(.exls)を扱う場合は以下の通りに指定。
          application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
          
          image.png
      • メソッドリクエスト
        HTTPリクエストヘッダーにAcceptを追加
        image.png

        Acceptヘッダーでクライアントがサーバーに対して、どのメディアタイプを受け入れることができるかを指定する

      • 統合リクエスト
        統合レスポンスのHTTPヘッダーにメソッドリクエストのAcceptヘッダをマッピング
        image.png

      • 統合レスポンス
        メソッドレスポンスのHTTPヘッダーに統合レスポンスのContent-Typeヘッダをマッピング
        image.png

        Content-Typeヘッダーでレスポンスに含まれるデータのメディアタイプを指定する

      • メソッドレスポンス
        レスポンスヘッダーにContent-Typeヘッダーを追加
        image.png

  • 動作確認
    POSTMANにてAPIへのGETリクエストを行い、S3のファイルをダウンロードできることを確認する。

    image.png

    Acceptヘッダにて、エクセルのメディアタイプ「application/vnd.openxmlformats-officedocument.spreadsheetml.sheet」を指定しないとローカルでダウンロードされたファイルを正常に開けないので注意

0
0
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
0
0