2

I'm migrating a small node/express app to lambda functions using serverless.

My app is really simple. No authentication. Just 1 endpoint, allowing GET and POST. The problem is GET works, but I'm getting HTTP error 403 when I send POST request sending a binary file (docx file)

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

My serverless.yml file looks like this

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

After running sls deploy, an Amazon API Gateway is created and the function is deployed, but can't use POST to send binary files to my app.

This is probably a problem with API Gateway, but couldn't fix it.

EDIT

The first response is the correct one, with just a small change in the serverless.yml file. This is the right one:

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+}'
Jorge Arévalo
  • 2,858
  • 5
  • 36
  • 44
  • [This](https://stackoverflow.com/questions/40988051/getting-message-forbidden-reply-from-aws-api-gateway) thread might contain some useful information to resolve your issue – PPetkov May 10 '19 at 12:22

1 Answers1

1

I think you are mixing up a few concepts:

  • You only have one function. I am not sure why you are defining two on your serverless.yml file
  • You have many methods under ONE function because you are delegating everything to express to handle.
  • If you wanted to have multiple functions, every one mapped to a different HTTP method, then you would not need to use Express
  • You are declaring PROXY, ANY, GET and POST, all under / (Although not sure, I think this is the root of your problem as API Gateway is getting lost on the routes). You don't need it if you're using Express as all you need is to proxy every single call.

With all of that said, you should modify your serverless.yml file accordingly:

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+}'

I have slightly changed your app.js file, but that was only to make it a little clearer to me, but you can always use it to compare against yours:

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

If you now deploy with sls deploy, you will be able to execute both methods successfully.

I have run both examples for you.

Issuing a GET results in:

enter image description here

And issuing a POST results in:

enter image description here

which is exactly what you are expecting.

Thales Minussi
  • 6,965
  • 1
  • 30
  • 48
  • 1
    Many thanks! I think I'm almost here. Just one thing: To send the POST request, I had to configure Postman Authorization to AWS Signature type. After that, I got this error to POST request: Credential should be scoped to a valid region, not 'us-east-1'. So, this is a credentials problem now. – Jorge Arévalo May 13 '19 at 09:47
  • I think you should change that to `eu-west-3` which matches your endpoint region. Please take a look here: https://github.com/aws/aws-sdk-java/issues/1097 – Thales Minussi May 13 '19 at 09:51
  • Usually the region is configurable via `AWS.config.update({region: 'eu-west-3'})` – Thales Minussi May 13 '19 at 09:52
  • I just checked it in Postman and the AWS Signature via it always defaults to 'us-east-1' so you have to manually set 'eu-west-3' and it should do it – Thales Minussi May 13 '19 at 10:17
  • Yep, I did that exactly. Many thanks. Now I'm facing this error, using exactly the same app.js file that yours: "message": "No method found matching route / for http method POST.". Working on it. – Jorge Arévalo May 13 '19 at 11:37
  • 1
    I had to add this to serverless.yml, inside the events section: http: POST /. But it worked! Thanks, because the response is totally based in this one. – Jorge Arévalo May 13 '19 at 11:48