2

I have an nginx reverse proxy that cannot get assets from an upstream mean stack server. It's a single page app that is very small. The index file will load just fine but all assets respond with 404 not found. It works locally when I have <base href="/"> but that does not work through the proxy. I've read and implemented the suggestions from proxying nginx Express - 404 on static files and NginX proxying Nodejs/Express - 404 on static files and read this article about replacing express static routing with nginx to help me solve this issue but none have worked.

The request uri is simply

mydomain.com/myApp

and the folder structure looks like:

myApp
├── app
└── public
    ├── css
    ├── js
    └── views

nginx config:

   1  server {
   2     listen 80;
   3 
   4     server_name mydomain.com;
   5
   6     location ~ ^/myApp/(libs/|img/|js/|css/) {
   7         root /path/to/myApp/public;
   8         access_log off;
   9         expires max;
  10     }
  11
  12     location /myApp {
  13         proxy_pass http://mean-stack-ip:8080;
  14         proxy_http_version 1.1;
  15         proxy_set_header Upgrade $http_upgrade;
  16         proxy_set_header Connection 'upgrade';
  17         proxy_set_header Host $host;
  18         proxy_cache_bypass $http_upgrade;
  19     }
  20 }

server.js:

   1 // server.js
   2 
   3 // modules =================================================
   4 var express        = require('express');
   5 var app            = express();
   6 var bodyParser     = require('body-parser');
   7 var methodOverride = require('method-override');
   8 
   9 // set our port
  10 var port = process.env.PORT || 8080;
  11 
  12 // get all data/stuff of the body (POST) parameters
  13 // parse application/json 
  14 app.use(bodyParser.json());
  15 
  16 // parse application/vnd.api+json as json
  17 app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
  18 
  19 // parse application/x-www-form-urlencoded
  20 app.use(bodyParser.urlencoded({ extended: true }));
  21 
  22 // override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT
  23 app.use(methodOverride('X-HTTP-Method-Override'));
  24 
  25 // set the static files location /public/img will be /img for users
  26 app.use(express.static(__dirname + '/public'));
  27 
  28 // routes
  29 require('./app/routes')(app); // configure our routes
  30 
  31 // startup our app at http://localhost:8080
  32 app.listen(port);
  33 
  34 // shoutout to the user                     
  35 console.log('Server listening on port ' + port + ' ...');
  36 
  37 // expose app
  38 exports = module.exports = app;

app/routes.js:

   1 // app/routes.js
   2 
   3 module.exports = function(app) {
   4 
   5     // route to handle all angular requests
   6     app.get('/myApp', function(req, res) {
   7         res.sendfile('./public/views/index.html');
   8     });
   9 
  10 };

index.html:

   1 <!doctype html>
   2 <html lang="en">
   3 
   4 <head>
   5     <meta charset="UTF-8">
   6     <base href="/myApp/">
   7     <meta name="viewport" content="width=device-width, initial-scale=1">
   8 
   9     <title>My App</title>
  10     
  11     <!-- CSS -->
  12     <link rel="stylesheet" href="libs/bootstrap/dist/css/bootstrap.min.css">
  13     <link rel="stylesheet" href="libs/font-awesome/css/font-awesome.min.css">
  14     <link rel="stylesheet" href="css/style.css">
  15 
  16     <!-- JS -->
  17     <script src="libs/jquery/dist/jquery.min.js"></script>
  18     <script src="libs/bootstrap/dist/js/bootstrap.min.js"></script>
  19     <script src="libs/angular/angular.min.js"></script>
  20     <script src="libs/angular-route/angular-route.min.js"></script>
  21 
  22     <!-- ANGULAR -->
  23     <script src="js/controllers/mainController.js"></script>
  24     <script src="js/appRoutes.js"></script>
  25     <script src="js/app.js"></script>
  26 </head>
  27 
  28 <body ng-app="myApp" ng-controller="mainController as main">
  29     <div id="body-container" class="container-fluid">
  30         
  31         <!-- Angular dynamic content -->
  32         <div ng-view></div>
  33 
  34     </div>
  35 </body>
  36 
  37 </html>

I'm new to mean stack and brand new to nginx so any help will be greatly appreciated. I'm essentially blocked from building anything further because I can't serve my apps!

Thanks in advance,

Amr

bschlueter
  • 3,817
  • 1
  • 30
  • 48
Amr Gaber
  • 33
  • 1
  • 5
  • Im having a similar issue where I want to access a NodeJS application using `/myapp` in the nginx conf file. I can get it to serve the static `index.html` not other JS files are not found because of the incorrect redirect. – David Oct 19 '16 at 14:38

2 Answers2

2

You could try proxying all requests instead of just /myApp.

Ray Haynes
  • 36
  • 2
  • 5
    @AmrGaber could you please elaborate how you fixed it – Asiri Liyana Arachchi Sep 07 '16 at 17:15
  • If you have multiple services running behind the nginx gateway this wont work. Your might have `/app1` and `/app2` that need to be redirected to a specific port number. – David Oct 19 '16 at 14:39
  • 1
    @mortond then what is the solution for multiple apps? – Isaac Pak Oct 28 '16 at 15:18
  • @IsaacPak my solution to this problem was to create 2 .conf file directories, one directory was for applications which defined `server` domain level configurations for applications like `todo.example.com` or `skynet.example.com`. The other .conf directory was for `location`s like `/api1/` or `/api2`. These config files where included in my main nginx.conf file at different positions `include /etc/nginx/conf.d/apis/*.conf;` and `include /etc/nginx/conf.d/applications/*.conf;` For the `server` level configs the `location` was `/` and for API level the `location`s were `/api/` or `/endpoint/` – David Nov 03 '16 at 14:24
  • nice. I have the same setup as the op. But my solution was to add the app root directory to the express static function. So in the op's case I would do something like: app.use('/myApp', express.static(__dirname + '/public')); – Isaac Pak Nov 07 '16 at 23:07
0

I was getting the same error in my logs when I using docker container links to connect my containers like in some of the older documentation. Docker container networking is the thing to use. I have another post with more details here and my web site www.starbug.com uses this and has links to my git repo with the full source.

I didn't want to duplicate my answer in the other post, but the basic idea is to create a docker network and refer to the containers by their names in the configuration file. This is what worked for me:

docker network create nginx-proxy

docker run --net nginx-proxy --name nginx-ss-00.starbug.com -v /var/run/docker.sock:/tmp/docker.sock -d -p 80:80 -p 443:443 nginx-ss.starbug.com

docker run --net nginx-proxy --name aai-gunicorn-00 -d -p 8080:8080 aai-gunicorn

and in my nginx conf

server {

    server_name  www.starbug.com;
    listen       80;

    # reverse proxy
    location / {

        # TODO Assumes flask container is named aai-gunicorn-00 and running on port 8080
        proxy_pass http://aai-gunicorn-00:8080;

        # Redefine the header fields that NGINX sends to the upstream server
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        client_max_body_size 5M;

    }

}