AWS API Gatewayから SVG(content-type: image/svg+xml)を返却する

WEBクライアントのJavaScriptからAWS API GatewayのGETメソッドを呼び出して、SVGファイルを取得する。

Lambdaを定義

以下のLambda「svgImageGet」を定義する。パラメータに応じたSVGファイルをS3からダウンロードしてAPI Gatewayへ返す関数。

const AWS = require("aws-sdk");
const S3 = new AWS.S3();
exports.handler = async (event) => {
    let responseBody = { svg: null };
    let params = {
        Bucket: "myBucket",
        Key: `svg/${event.bodyName}.svg`,
    };
    let s3obj = await (new Promise((resolve, reject) => {
        S3.getObject(params, (err, data) => {
            if(err) {
             reject(err);
            } else {
          resolve(data);
         }
        });
    }));
    responseBody.svg = s3obj.Body.toString("utf-8");
    return responseBody;
};

API Gateway の設定

前提: 任意のAPIにCORSが有効化されたメソッド:/svg-file GETが定義されている状態。

以降このGETメソッドに対する設定。

「メソッドリクエスト」の設定

「メソッドリクエスト」の「URL クエリ文字列パラメータ」にパラメータbodyNameを追加。

「統合リクエスト」の設定

「統合リクエスト」で上記Lambdaに紐づけて、content-typeapplication/jsonの「本文マッピングテンプレート」を追加。内容は以下。

{
    "bodyName" : "$input.params('bodyName')"
}

上記$input.params('bodyName')が「メソッドリクエスト」の「URL クエリ文字列パラメータ」を指しており、このJSON全体が、Lambdaの第一引数に渡される。

「統合レスポンス」の設定

「統合レスポンス」の「本文マッピングテンプレート」で、「リクエスト本文のパススルー」から「テンプレートが定義されていない場合 (推奨)」を選んでおき(デフォルト)content-typeimage/svg+xml
のマッピングテンプレートを追加する。テンプレートの内容は以下とする。

#set($inputRoot = $input.path('$'))
$inputRoot.svg

テンプレートの $inputRoot.svg が、LambdaのresponseBody.svgに対応している。

「メソッドレスポンス」の設定

HTTPのステータス 200 を開き、「200のレスポンス本文」のContent-Typeをimage/svg+xmlとする。モデルは空(Empty)で良い。

API Gatewayの呼び出し

これまで設定してきたAPIを任意のステージへデプロイした上で、JavaScriptのSDKをダウンロードする。

このSDKはHTMLのSCRIPTタグで読み込んでおき、以下の関数を実行すれば、SVGドキュメントを取得できる。

/* globals Promise, apigClientFactory */
"use strict";

let apigClient = apigClientFactory.newClient({
    apiKey: "apiKey",
});

/**
 * @async
 * @param {string} bodyName ファイルボディ名
 * @returns {Promise<xmldoc>} SVGドキュメントを返す。
 */
async function svgFileGet(bodyName) {
    let response = await apigClient.svgFileGet(
        { bodyName: bodyName }, {}, {});
    if(response == null) {
        throw new Error("Null response");
    } else if(!("status" in response)) {
        throw new Error("No status in response");
    } else if(response.status !== 200) {
        throw new Error("Request fail");
    } else if(!("data" in response)) {
        throw new Error("No data in response");
    }
    let parser = new DOMParser();
    return parser.parseFromString(
      response.data, "image/svg+xml");
};

0 件のコメント: