Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

node.js - Express 4, NodeJS, AngularJS routing

I am using Express 4 to host my AngularJS app on my backend, with Nginx as my frontend server. However html5 mode does not seem to work, as I will get a Cannot /GET error when I try to enter the page link (e.g. http://localhost/login) via the browser. Is there any routing configuration I need to do for my Express/Nginx? Here's my config code:

Express 4:

var express = require('express'),
    app = express(),
    server = require('http').Server(app),
    bodyParser = require('body-parser'),
    db = require('./db'),
    io = require('./sockets').listen(server),
    apiRoutes = require('./routes/api'),
    webRoutes = require('./routes/web');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use('/api', apiRoutes);
app.use(express.static(__dirname + '/public'));

server.listen(3000, function() {
  console.log('Listening on port %d', server.address().port);
});

AngularJS:

'use strict';
var nodeApp = angular.module('nodeApp',['ngRoute']);

nodeApp.config(function($routeProvider, $locationProvider, $controllerProvider) {
  $routeProvider.when('/', {
    templateUrl: 'partials/home.html'
  }).when('/login', {
    templateUrl: 'partials/login.html'
  });
  $locationProvider.html5Mode(true);

  nodeApp.controllerProvider = $controllerProvider;
});

Nginx:

# the IP(s) on which your server is running
upstream test-app {
  server 127.0.0.1:3000;
}

# the nginx server instance
server {
  listen 0.0.0.0:80;
  server_name test-app.cloudapp.net;
  access_log /var/log/nginx/test-app.log;

  # pass the request to the nodejs server with correct headers
  location / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Nginx-Proxy true;

    proxy_pass http://test-app/;
    proxy_redirect off;
  }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'm assuming you are using a "single page" angular app, so one html page that uses ng-view to load all the other partials.

In this case you need to do something like this:

Express 4:

var express = require('express'),
    app = express(),
    server = require('http').Server(app),
    bodyParser = require('body-parser'),
    db = require('./db'),
    io = require('./sockets').listen(server),
    apiRoutes = require('./routes/api'),
    webRoutes = require('./routes/web');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use('/api', apiRoutes);
app.use(express.static(__dirname + '/public'));
// Here's the new code:
app.use('/*', function(req, res){
  res.sendfile(__dirname + '/public/index.html');
});

server.listen(3000, function() {
  console.log('Listening on port %d', server.address().port);
});

The problem you're facing is that even though you have routes setup for '/login' before the routes are fired they need to be loaded. So the server tries to find a match for the route '/login' which it can't returning the 404. In the case of single page angular apps all the routes you use in routing must be caught by a route, app.get('/*', ... in this case, and then return the main angular.js html page. Note that this is the last call so it will be evaluated last, if you put it first it will prevent all the subsequent rules from running as express just runs the handler for the first rule it encounters.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...