web-dev-qa-db-ja.com

AWS API GatewayとLambdaが画像を返す

このHTMLがあるとします。

<img src="http://example.com/pic"/>

私がやりたいのは、example.com/picをAWS API Gatewayエンドポイントにマップすることです。

次に、そのエンドポイントはラムダ関数を呼び出します。

そのラムダ関数は、s3バケットからランダムな画像を読み取り、それを返します。

したがって、私の目的は、STANDARD HTML画像タグを使用して、s3バケットからの画像で終わることですが、ラムダ内のいくつかの決定コードを経由して、返す画像を決定します。

私はあなたがs3を使用して静的コンテンツを直接提供できることを知っています(したがってラムダはどのイメージについて決定を下すか)。また、b64などのラムダで応答をエンコードしてクライアントで処理できることも知っていますが、標準のHTML IMGタグを使用することを目指しています。

これは可能ですか?

ラムダにResponseStreamHandler(Java SDK)を使用して画像のバイト配列を返し、APIゲートウェイ構成を追加して出力をJSONにマップしないようにしましたが、何も動作しないようです!

14
user1736191

AWSはこのプロセスを簡略化しているため、多くの回答が古くなったり、過度に複雑になったりしています。

これは、2018年6月の時点で、LambdaにAPI Gatewayを介して画像を返す方法です。

1)API Gatewayで、Use Lambda Proxy integrationをAPIに使用します。 (この設定は、タイプをLambdaに設定したIntegration Requestセクションにあります。)

2)API GatewayでAPIを選択し、Settingsをクリックします。 Binary Media Types 追加 */*。 (注:単に「image/jpeg」を追加してみましたが、*/*これをすべて機能させるには)

3)必ずAPIをデプロイしてください。デプロイしないと、変更が反映されません。 (API Gatewayで、APIを選択し、[アクション]> [APIのデプロイ]を選択します)。

4)Lambdaコードで、Base64エンコーディングで画像を返します(この例はC#コードです)。

    // set the Content-type header
    // set to whichever image type you're returning
    var headersDic = new Dictionary<string, string>();
    headersDic.Add("Content-type", "image/jpeg");

    // return the response object that APIGateway requires
    return new APIGatewayProxyResponse
    {
        StatusCode = 200,
        Headers = headersDic,
        // return the image in Base64 encoding
        Body = Convert.ToBase64String(...your image data...),
        IsBase64Encoded = true
    };

できました。

認証を必要としないようにAPIを設定した場合は、ブラウザにAPIリンクを入力するだけで画像が表示されます。または、APIリンクをIMGタグに挿入します。例えば<img src="https://asdf.execute-api.us-east-1.amazonaws.com/live/myapi" />

注:ステップ2でBinary Media Types*/*、Lambdaが返すテキストであれば、API Gatewayはテキストを返します。

22
Doug S

幸い、AWS API Gatewayはバイナリデータをサポートしていますが、コンソールにはまだ実装されていないため、CLIを介してリソースメソッドを更新する必要もあります。これはあなたがする必要があることです:

  1. メソッドのMethod Response
    HTTP 200ステータス応答ヘッダーでContent-Typeimage/jpegとして設定します
  2. メソッドのIntegration Response
    ヘッダーマッピングでContent-Type'image/jpeg'として設定します。 引用符に注意してください!
  3. AWS CLIを使用して、統合応答でcontentHandling属性をCONVERT_TO_BINARYに設定します

このすばらしいステップバイステップガイドでプロセス全体を確認してください: https://stackoverflow.com/a/41434295/720665

7
David Salamon

同様の問題に遭遇しました。すでに述べたように、現在、API Gatewayエンドポイントからイメージをバイナリ形式で直接返すことはできません。これは、ブラウザーがイメージを正しく表示するために必要です。

ただし、APIゲートウェイに2 Redirectを返させ、S3の正しいファイルを指すようにすることで、これを解決しました。 Lambda関数でURLをファイルに返すことができます。このファイルは後でAPI GatewayのLocationヘッダーにマッピングされます。ブラウザはリダイレクトに従い、画像を適切に表示します。

リダイレクトを実装する方法はいくつかありますが、私は次のようにしました:

  • Lambdaは次のようにターゲットイメージを含むオブジェクトを返します。

    function handler(event, context) {
         context.succeed({ 
             location: "https://[bucket-name].s3-eu-west-1.amazonaws.com/myimage.png" });
         });
    }
    
  • API Gatewayの統合応答から通常の「200」メソッド応答ステータスを削除します。それを「302」応答ステータスに置き換え、「Location」ヘッダーを値「integration.response.body.location」にマップします

  • メソッドレスポンスにも302ステータスを追加します

5
Theodor

明確にするために、クライアントは2つの異なる要求を行います。

  1. HTML(画像のURLを含む)を最初に取得します。
  2. URLから画像データを取得する2番目の方法。

つまり、画像データはHTMLにインライン化されません。

この知識に基づいて、あなたが提案するように(APIゲートウェイの後ろに)Lambdaを持つことができます。 Lambda実装には、S3に保存されている画像のURLを決定するロジックを含めることができます。ただし、LambdaはHTMLではなくJSONデータを返します(変数にHTMLを返す HTMLを返す などの回避策があります)。これは、特に大きなHTMLの場合、より複雑になります。ページ。

イメージタグを受け取っただけでは十分ではないため、少し異なるアプローチをお勧めします。おそらくJavaScriptを使用して、HTMLドキュメントのイメージタグをインライン化することを想定しています。次に、API Gateway/Lambdaリクエストに画像URLを含むJSONドキュメントを返させ、JavaScriptで既存の画像タグを新しいURLで更新するか、タグを生成することもできます。

1
matsev

現在、AWS API Gatewayを介してバイナリデータを返すことができないため、これはできません。

これを機能させるには、ラムダ関数が画像データをバイナリBLOBとして返し、画像コンテンツタイプなどのメタ情報を返す必要があります。次に、AWS API GatewayはこれをHTTP応答にマップできる必要があります。例えば:-

ラムダは以下を返します:{ contentType: 'image/png', image: "encoded binary data" }

aPIゲートウェイは、contentTypeを応答の 'content-type'ヘッダーにマップし、正しいエンコードと長さで画像データを応答の本文に配置する必要があります。

残念ながら、現時点ではこれはできません。 application/jsonやapplication/xmlなどのテキストエンコーディングのみを応答タイプとしてマッピングします(結局のところ、API向けに設計されています)。

ElasticBeanstalkを使用すると、http応答をより詳細に制御できるため、非常に簡単にこれを実現できます。

0
aomega