Бессерверная функция AWS не отвечает изображением

Я пытаюсь, чтобы AWS API Gateway ответил изображением. Мой код Serverless Lambda выглядит следующим образом

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)

безсерверный.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

Изображение, которое возвращается, — это черный ящик. введите здесь описание изображения


person mbejda    schedule 23.02.2019    source источник


Ответы (2)


Работа с двоичными файлами в API Gateway — это всегда проблема. Однако мне удалось заставить его работать.

Все, что вам нужно сделать, это сообщить API Gateway, что ваш ответ закодирован в base64.

Вот рабочее решение:

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

};

Однако реальная проблема, которую я здесь вижу, заключается в том, что Express управляет маршрутами вместо вас, поэтому я не думаю, что вы можете перехватить ответ API GW, чтобы добавить поле «isBase64Encoded», поэтому я боюсь, что вам придется позволить этому API управлять API Gateway вместо Express, чтобы он работал правильно.

Кроме того, Jimp предлагает метод getBufferAsync, который возвращает промис, так что вы можете просто await использовать его, чтобы немного упростить код.

Надеюсь, поможет!

ИЗМЕНИТЬ:

Я все еще пытался заставить его работать с Express, поэтому нашел это: https://github.com/awslabs/aws-serverless-express/issues/99#issuecomment-332169739

Я должен признать, что не проверял, но это может сработать, если вам действительно нужно, чтобы Express обрабатывал маршруты за вас.

введите здесь описание изображения

person Thales Minussi    schedule 23.02.2019

ХОРОШО. Я только что прошел через это и подумал, что поделюсь решением. Проблема связана с несоответствием между Serverless и AWS. Таким образом, мы собираемся получить их обоих на одной странице.

ПЕРВЫЙ->Бессерверная конфигурация

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

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

Это настраивает Serverless для сервера связанных типов Mime как Base64.

ВТОРОЙ-> Конфигурация AWS

В AWS API выберите «Шлюз», а затем «Настройки». Прокрутите вниз и добавьте следующие двоичные типы:

Конфигурация AWS

Вот и все! Теперь это должно работать!

person Scott Nichols    schedule 16.11.2019
comment
я не знаю, сколько ревизий Buffer.from res.send res.end я просмотрел, прежде чем нашел это. АГВ/уровень сервера! фу. спасибо! - person sonjz; 07.07.2021