AWS API Gateway and Lambda to return image

后端 未结 5 2209
情书的邮戳
情书的邮戳 2021-02-19 06:02

Say I have this HTML:


What I would like to do is have example.com/pic map to an AWS API Gateway end

相关标签:
5条回答
  • 2021-02-19 06:39

    I've run in to a similar problem. As mentioned you currently can't directly return your image in binary format from your API Gateway endpoint, which would be required for the browser to display it correctly.

    However, I solved this by instead having API Gateway return a 302 Redirect, pointing to the correct file in S3. You can have your Lambda function return the url to the file, which is later on mapped to the Location header in API Gateway. The browser will follow the redirect and display the image properly.

    There are several ways to implement the redirect, but I did as follow:

    • Lambda returns an object with the target image like so:

      function handler(event, context) {
           context.succeed({ 
               location: "https://[bucket-name].s3-eu-west-1.amazonaws.com/myimage.png" });
           });
      }
      
    • Remove the normal '200' Method Response Status from The Integration Response in API Gateway. Replace it with a '302' response status and add the 'Location' header mapped to value 'integration.response.body.location'

    • Add the 302 status to the Method Response as well

    0 讨论(0)
  • 2021-02-19 06:44

    Luckily, now AWS API Gateway supports binary data, though you also need to update your resource method through the CLI as it is not yet implemented in the Console. This is what you need to do:

    1. In the Method Response of your method
      Set Content-Type as image/jpeg in HTTP 200 Status Response Header
    2. In the Integration Response of your method
      Set Content-Type as 'image/jpeg' in Header Mappings. Mind the quotes!
    3. With the AWS CLI, set contentHandling attribute to CONVERT_TO_BINARYon your Integration Response

    Check to entire process in this great step-by step guide: https://stackoverflow.com/a/41434295/720665

    0 讨论(0)
  • 2021-02-19 06:51

    It currently isn't possible because you cannot return binary data through the AWS API Gateway.

    For this to work, the lambda function would need to return the image data as binary blob, and some meta-information such as the image content type. Then, AWS API Gateway would need to be able to map this to the HTTP response. For example:-

    lambda returns: { contentType: 'image/png', image: "encoded binary data" }

    then API gateway would need to map contentType to the 'content-type' header of the response, and put the image data in the body of the response with the right encoding and length.

    Unfortunately, it doesn't do this right now. It only maps text encodings like application/json or application/xml as the response type (it is designed for APIs after all).

    You could very easily achieve this using ElasticBeanstalk where you have a lot more control over the http response.

    0 讨论(0)
  • 2021-02-19 06:54

    Just to be clear, the client does two different requests:

    1. The first to get the HTML (including the image url).
    2. The second to fetch the image data from the url.

    In other words, the image data is not inlined in the HTML.

    Based on this knowledge you can have a Lambda (behind the API gateway) as you suggest. The Lambda implementation can have some logic that determines the url to the image stored in S3. However, the Lambda returns JSON data and not HTML (there are workarounds such as return the html in a variable) which makes things trickier, especially for large HTML pages.

    I suggest a slightly different approach, since just receiving an image tag will not get you far. I assume you will inline the image tag in a HTML document, probably by using JavaScript. Then you might as well let the API Gateway / Lambda request return a JSON document with the image url and let the JavaScript either update an existing image tag with the new url or generate the tag for you.

    0 讨论(0)
  • 2021-02-19 06:58

    It seems AWS has simplified this process, so that many answers are outdated and/or overly complicated.

    This is how I got Lambda to return an image through the API Gateway, as of June 2018:

    1) In API Gateway, enable Use Lambda Proxy integration for your API. (This setting is located on the Integration Request section, where you had set the type to Lambda.)

    2) In API Gateway, select your API and click Settings. In Binary Media Types add */*. (Note: I tried adding simply 'image/jpeg', but it seems to require */* to get all of this to work)

    3) Be sure to deploy your API, otherwise your changes will not be live. (In API Gateway, select your API, then Actions > Deploy API).

    4) In your Lambda code, return your image in Base64 encoding (this example is C# code):

        // 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
        };
    

    Done.

    If you've setup your API to not require authentication, simply type your API link into your browser, and it will display the image. Or put the API link into an IMG tag. e.g. <img src="https://asdf.execute-api.us-east-1.amazonaws.com/live/myapi" />

    Note: Even though in step 2 you set the Binary Media Types to */*, API Gateway will still return text if that is what your Lambda is returning.

    0 讨论(0)
提交回复
热议问题