9

I have a node application running on a service with Apache and Nginx as a reverse proxy.

On the same server also a Node REST API is running.

The JavaScript code looks as follows:

api.js

// Express
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');

// Express App
const app = express();

// Env
const PORT     = process.env.PORT || 3000;
const NODE_ENV = process.env.NODE_ENV || 'development';

// Config
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());

// Routes
const users = require('./routes/users');

// Angular Http content type for POST etc defaults to text/plain at
app.use(bodyParser.text(), function ngHttpFix(req, res, next) {
  try {
    req.body = JSON.parse(req.body);
    next();
  } catch(e) {
    next();
  }
});

app.use('/api', users);

app.listen(PORT, function() {
   console.log('Listen on http://localhost:' + PORT + ' in ' + NODE_ENV);
});

/routes/users.js

var models  = require('../models');
var express = require('express');
var router = express.Router();

// get all users
router.get('/users', function(req, res) {
  models.Beekeeper.findAll({}).then(function(users) {
    res.json(users);
  });
});

module.exports = router;

The Nginx configuration looks as follows:

index   index.html index.htm;

upstream api {
    server 127.0.0.1:3000;
}

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443;
    root /var/www;

    ssl on;
    ssl_prefer_server_ciphers On;
    ssl_protocols TLSv1.2;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;

    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;

    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_certificate /etc/letsencrypt/live/example.com/cert.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    server_name example.com;

    location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

    }

    location /api {
            proxy_pass http://api;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            rewrite ^/api/?(.*) /$1 break;
            proxy_redirect off;
    }
}

The problem is that if I make an API call on my development server, for example, localhost:3000/api/users, it works as expected.

However, if I make an API call on my production server, for example, https://example.com/api/users, I get Cannot GET /users and 404 NOT FOUND, respectively.

I suppose that there is something wrong with my Nginx configuration, however, although I already read numerous other posts about similar problems here on Stackoverflow, I could not solve the problem.

3
  • what shows on you browser if you directly hit http://api? Commented May 3, 2017 at 9:27
  • @FazalRasel do you mean example.com/api ? Commented May 3, 2017 at 9:30
  • no, proxy_pass will call just http://api as your configuration. I guess it return 404 Commented May 3, 2017 at 9:31

1 Answer 1

11

Notice that you're requesting this:

https://example.com/api/users

But the error says this:

Cannot GET /users

So the /api prefix is being stripped off the request path before being passed to your Node server.

Which is done by this line:

rewrite ^/api/?(.*) /$1 break;

Solution: remove that line.

Sign up to request clarification or add additional context in comments.

5 Comments

if I remove that line and request example.com/api/users the result is 404 Not Found nginx/1.10.2, which means that the API cannot be reached anymore
I tested with a very similar setup and it works just fine for me. Does your Express server log the request, or does NGINX not even pass the request on?
your answer is fine, I have done some debugging and found out that my ORM threw an error due to a missing environment variable. Sorry for the confusion.
@MichaelAndorfer mind if I ask what is that environment variable? Is that something to do with Nginx alone or with your app itself?
@JovanniG it has nothing to do with nginx, you don’t need to mind this ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.