2015-05-18 94 views
2

我有兩個由Nginx提供服務的由Express支持的NodeJS應用程序。一個應用程序是一個RESTful API,由Angular SPA使用,另一個是管理員門戶。這是我想在這裏實現:如何使用反向代理處理Express應用程序中的重定向

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並且表達4.12.2。如果我必須在應用程序中添加任何第三方模塊,我沒有任何問題,但我更喜歡是否存在針對我的問題的nginx解決方案。

謝謝。

+0

你想要做的事絕對可行。只需確認,您是否在兩個獨立的快速應用程序上提供託管端口3010和3011? –

+0

您是否向我們展示了您的完整nginx配置?你在哪裏爲你的'/ *'路由配置'proxy_pass',例如'/ login'? –

+0

@AndrewLavers是的。他們是兩個不同的應用程序這是我完整的nginx配置。我錯過了什麼? – Umayr

回答

0

與你的nginx配置的問題是爲/admin路線重寫:

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

有了這個規則的地方你的管理門戶節點的應用程序不知道它的路徑都舉辦過一個/admin根,所以如果你的應用做了一個相對於它認爲是根的重定向,例如res.redirect('/login'),那麼它將把瀏覽器發送到localhost/login是有道理的。

另一種方法是刪除你的nginx rewrite,並讓管理門戶知道這個/admin路徑。這樣,您可以選擇重定向到相對路徑,如下所示: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

刪除重定向指令不適用於我。對於您提供的最後一個選項,是否必須使用'res.redirect(path.join(res.mountedAt,'/ login'));'我在哪裏重定向用戶? – Umayr

+0

如果您重定向到位於/ admin下的另一個管理頁面,那麼是。 –

+0

這是否解決了您的問題?我在類似的情況下,我的nginx反向代理髮送所有'/ app'請求到我的nodejs應用程序。問題在於,一旦Angular Index和core.js加載到瀏覽器中,對nodejs REST API的調用就會丟失nginx路由請求所需的'/ app /'前綴。我只是得到一個'不能GET/api /端點'它應該擊中'/ app/api /端點' – David

相關問題