Search code examples
node.jsapiamazon-ec2nginx-reverse-proxyhttp-status-code-504

Why do EC2/Node.js GET requests work but POST aren’t even routed?


Variations of my issue have been asked dozens of times, but nothing I’ve tried worked.

My Node.js API works as expected on localhost for GET and POST requests.

On my EC2/nginx instance, the server block was correctly configured and served a static index over https.

Then I configured this server block as a proxy to my API port (8000) and it also returns that the API is listening.

Then I ran a simple GET /index endpoint that is routed and works correctly.

However, a similar POST /checkEmail endpoint (which, remember, works on localhost) here times out with a 504 error. This is where it gets weird.

It won’t even console.log the payload, the first line of the function. That means it isn’t even routed correctly. Here are my routes:

const API = require("./controllers/api");

module.exports = [
    { method: 'POST', path: '/checkEmail', options: API.checkEmail },
    { method: 'POST', path: '/sendEmail', options: API.sendEmail },
    { method: 'POST', path: '/recaptcha', options: API.recaptcha },
    { method: 'GET', path: '/index', options: API.index }
    
]

Since that the GET request returns the expected response, then it means all of these are true:

  • The firewall rules are letting traffic through the 443 (HTTPS) port
  • That traffic is proxied through the 8000 (API) port
  • The server block is serving the files correctly
  • The ssl certificate works
  • The request is sent to the upstream server

The endpoints:

const axios = require("axios");
const env   = require("dotenv").config();

const AWS = require("aws-sdk");

const subscriber = require("./middleware/subscriber");
const sanitizer  = require("./middleware/sanitizer");

exports.index = {
    cors: {
        origin: ["*"]
    },

    handler: (request, h) => {
        return "API Fluente";
    }
}

exports.checkEmail = {
    cors: {
        origin: ["*"]
    },
  
    handler: async (request, h) => {
        // This is never logged:
        console.log(request.payload);
        const payload = request.payload;
        const email = await sanitizer.email(payload.email);

        if(!email) throw new Error("Invalid email");

        const response = await verifyEmail(email);
        console.log("checkEmail attempt:", email, response.data)

        if (response.status === 200) {
            return h.response(response.data).code(200);
        }

    }
}

What I’ve tried:

  • Minimal/Full server block conf settings
  • curl the POST request from the EC2 CLI
  • Change ports from 8000 to something else (eg 8003)
  • Increasing timeout duration doesn’t make sense because these are simple requests that should return a response in a very short time.

None of these made any difference.


Solution

  • Found the problem! As it turns out, it had nothing to do with AWS services or Node.

    I was using the deprecated hapi package, when I should have been using @hapi/hapi.