通过 POST 发送文件时,AWS lambda 函数 returns HTTP 403

AWS lambda function returns HTTP 403 when sending file via POST

我正在使用无服务器将小型 node/express 应用程序迁移到 lambda 函数。

我的应用程序非常简单。没有身份验证。只有 1 个端点,允许 GET 和 POST。 问题是 GET 有效,但是当我发送 POST 请求发送二进制文件(docx 文件)

时,我收到 HTTP 错误 403
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static(path.join(__dirname, 'public')));


/* GET home page. */
app.get('/', function (req, res, next) {
    res.render('index', {title: 'Whatever'});
});

/* POST receive file */
app.post('/', function (req, res, next) {
    // Simplified to the minimum
    return res.json({'msg': 'ok'});   
});

module.exports.handler = serverless(app);

我的 serverless.yml 文件看起来像这样

service: my_service

provider:
  name: aws
  runtime: nodejs8.10
  stage: dev
  region: eu-west-3

functions:
  app:
    handler: app.handler
    events:
      - http: GET /
      - http: 'ANY {proxy+}'
  post:
    handler: app.handler
    events:
      - http:
          path: /
          method: post
          cors: true

运行sls deploy后,创建了一个亚马逊API网关并部署了函数,但是无法使用POST将二进制文件发送到我的应用程序。

这可能是 API 网关的问题,但无法修复。

编辑

第一个响应是正确的,只是 serverless.yml 文件中的一个小改动。这是正确的:

service: my-service

provider:
  name: aws
  runtime: nodejs8.10
  stage: dev
  region: eu-west-3

functions:
  app:
    handler: app.handler
    events:
      - http: GET /
      - http: POST /
      - http: 'ANY {proxy+}'

我认为您混淆了一些概念:

  • 你只有一个功能。我不确定为什么要在 serverless.yml 文件
  • 上定义两个
  • 你在一个函数下有很多方法,因为你把所有要表达的东西都委托给处理。
  • 如果你想拥有多个功能,每个功能都映射到不同的 HTTP 方法,那么你就不需要使用 Express
  • 您正在声明 PROXY、ANY、GET 和 POST,都在 / 下(虽然不确定,但我认为这是您问题的根源,因为 API 网关正在迷路了)。如果您使用 Express,则不需要它,因为您需要的只是代理每个调用。

综上所述,您应该相应地修改 serverless.yml 文件:

service: my-service

provider:
  name: aws
  runtime: nodejs8.10
  stage: dev
  region: eu-west-3

functions:
  app:
    handler: app.handler
    events:
      - http: ANY /
      - http: 'ANY {proxy+}'

我稍微更改了您的 app.js 文件,但这只是为了让我更清楚一点,但您可以随时使用它与您的文件进行比较:

const serverless = require('serverless-http');
const express = require('express')
const app = express()
const bodyParser = require('body-parser');

app.use(bodyParser.json({ strict: false }));

/* GET home page. */
app.get('/', function (req, res, next) {
    res.json({title: 'Whatever'});
});

/* POST receive file */
app.post('/', function (req, res, next) {
    // Simplified to the minimum
    return res.json({'msg': 'ok'});   
});

module.exports.handler = serverless(app);

如果您现在使用 sls deploy 进行部署,您将能够成功执行这两种方法。

我有运行两个例子给你。

发出 GET 结果:

并发出 POST 结果:

这正是您所期待的。