问题
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