AWS serverless function is not responding with an image

倖福魔咒の 提交于 2019-12-11 04:13:02

问题


I'm trying to have AWS API Gateway respond back with an image. My Serverless Lambda code is the following

const express = require('express');
const serverless = require('serverless-http');
const bodyParser = require('body-parser');
const request = require('request');
const fetch = require('node-fetch')
var Jimp = require('jimp');
const app = express()
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))

app.get('/image/:id', async(req, res) => {
    const id = req.params.id;

    var imgUrl = 'https://developer.salesforce.com/forums/profilephoto/729F00000005O41/T';
    let options = {};

    const image = await Jimp.read(imgUrl);
    image.getBuffer(Jimp.MIME_JPEG, (err, buffer) => {
        res.set('content-type', 'image/jpeg');
        res.send(buffer.toString('base64'));
    });
});
// wrap express app instance with serverless http function
module.exports.handler = serverless(app)

serverless.yml


provider:
  name: aws
  runtime: nodejs8.10
  stage: dev
  region: us-east-1
  memorySize: 512

custom:
  apigwBinary:
    types:           #list of mime-types
      - 'image/jpg'
      - 'image/jpeg'
      - 'image/png'
functions:
  avatarFunc:
    handler: index.handler
    events:
      - http:
          path: image/{id}
          method: get
          contentHandling: CONVERT_TO_BINARY

plugins:
  - serverless-offline
  - serverless-apigw-binary

The image that is coming back is a black box.


回答1:


Dealing with binaries in API Gateway is always a hassle. I have managed to make it work, though.

All you need to do is tell API Gateway that your response is encoded in base64.

Here's a working solution:

module.exports.hello = async (event, context) => {
  const imgUrl = 'https://developer.salesforce.com/forums/profilephoto/729F00000005O41/T';
  const image = await jimp.read(imgUrl);
  const buffer = await image.getBufferAsync(jimp.MIME_JPEG);
  return {
    statusCode: 200,
    headers: {
      'content-type': 'image/jpeg'
    },
    body: buffer.toString('base64'),
    isBase64Encoded: true
  };

};

The real problem I see here, however, is that Express is managing the routes for you, therefore I don't think you can intercept API GW's response to add the field 'isBase64Encoded', so I am afraid you'll have to let this API be managed by API Gateway instead of Express in order to make it work properly.

Also, Jimp offers a getBufferAsync method which returns a promise, so you can just await on it to make the code slightly simpler.

Hope it helps!

EDIT:

I was still trying to make it work with Express, so I found this: https://github.com/awslabs/aws-serverless-express/issues/99#issuecomment-332169739

I must admit I did not test, but it may work if you really need to have Express handling the routes for you.




回答2:


OK. I just went through this and thought I'd share the solution. The problem is related to mismatch between Serverless and AWS. So we're going to get them both on the same page.

FIRST-> Serverless config

const binaryMimeTypes = {binary: [
  'image/*',
  'image/jpeg',
  'image/png',
  'image/svg+xml',
]};

module.exports.server = sls(app, binaryMimeTypes) 

This configures Serverless to server the associated Mime types as Base64.

SECOND-> AWS Config

In AWS API Select the Gateway and then Settings. Scroll down and add the following binary types:

That's it! It should work now!



来源:https://stackoverflow.com/questions/54840576/aws-serverless-function-is-not-responding-with-an-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!