如何使用反向代理在Express应用程序中处理重定向

问题描述 投票:3回答:2

我有两个由Nginx提供服务的Express Express NodeJS应用程序。一个应用程序是RESTful API,它由Angular SPA使用,另一个应用程序是管理门户。这是我要在这里实现的目标:

location / {
  # Serves Client Side Angular Application
}

location /api {
  # Serves RESTful Application
}

location /admin {
  # Serves Admin Portal
}

这是我对nginx的完整配置:

server { 
server_name localhost;
listen 80;
listen [::]:80;
index index.html;

location / { 
    expires -1; 
    add_header Pragma "no-cache"; 
    add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"; 
    root /var/www/example/client/dist;
    try_files $uri $uri/ /index.html =404; 
}

location /admin/ {
    proxy_pass http://127.0.0.1:3010/;
    proxy_http_version 1.1;
    rewrite /admin/(.*) /$1 break;
    proxy_redirect off;
    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/admin/;
    proxy_set_header X-NginX-Proxy true;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
} 

location /api { 
    proxy_pass http://127.0.0.1:3011;
    proxy_http_version 1.1;
    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_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}
} 

两个NodeJS应用程序都可以永久使用,并且可以完美地在其定义的端口上运行。

我在管理应用程序中遇到的问题,当我尝试点击http://example.com/admin时,它会将我重定向到http://example.com/login,而应将我重定向到http://example.com/admin/login。我试图通过向管理应用程序中添加中间件来解决此问题,例如:

app.use('*', function (req, res, next) {
 if(process.env.target === 'dev'){
   if(req.originalUrl.indexOf('/admin') > -1){
     res.redirect('/admin' + req.url);
   }
   next();
 }
});

但是这不起作用。我应该如何处理这种情况?无论如何,nginx是否可以处理应用程序重定向?如果不是,我应该如何在不同环境(Dev,Staging,Prod等)的应用程序中处理它?我正在使用nginx 1.4.6,节点0.12.2和Express 4.12.2。我不必在应用程序中添加任何第三方模块,但是我希望有一个解决我问题的Nginx解决方案。

谢谢。

angularjs node.js express nginx reverse-proxy
2个回答
0
投票

nginx配置的问题是对/admin路由的重写:

rewrite /admin/(.*) /$1 break;

使用此规则,您的管理门户网站节点应用程序不知道其路径全部托管在/admin根目录之外,因此,如果您的应用程序进行了相对于它认为是根目录的重定向,例如res.redirect('/login'),它将浏览器发送到localhost/login是有意义的。

一种替代方法是删除您的nginx rewrite,并使管理门户知道此/admin路径。这样,您可以选择重定向到relative路径,如下所示:res.redirect('login')告诉express考虑当前请求的路径。您可以使用express.Router使它更清洁,例如:

var adminRoutes = express.Router()
    .get('/', function(req, res) {
        if(!req.user) {
            // Will redirect to /admin/login
            res.redirect('login');
        } else {
            res.send('Hello');
        }
    })
    .get('/login', login);

// Tell express to host all routes above under a common /admin root
app.use('/admin', adminRoutes);

[另一方面,如果有更好的理由必须重写nginx,则始终可以为所有应用程序重定向手动手动包含/admin根目录。您可以通过从proxy_set_header设置的自定义标头中读取它来临时附加此安装路径。例如:

app.use(function(req, res, next) {
    res.mountedAt = req.headers['X-Mounted-At'];
    next();
});

app.get('/', function(req, res) {
    res.redirect(path.join(res.mountedAt, '/login'));
});

0
投票

我通过结合安德鲁·拉弗斯的第一个解决方案解决了这个问题

        location /admin/ {
        proxy_pass          https://127.0.0.1:3010/admin/;
    }
© www.soinside.com 2019 - 2024. All rights reserved.