一個使用struts2的網站在登入頁面需要進行redirect跳轉,大致如下:
<package name="admin" extends="httl-default" namespace="/admin">
<action name="login" class="com.zandili.tech.action.manage.LoginAdmin">
<result name="success" type="httl">/admin/login.httl</result>
<result name="error" type="redirect">/404</result>
<result name="loginok" type="redirect">/admin/index.do</result>
</action>
</package>
這是struts2中再簡單不過的邏輯了,本地測試一切正常,但經過nginx代理後,這個奇葩問題就出現了。
我們假定兩臺tomcat的webapps目錄下都有一個app目錄是我們網站應用的目錄,nginx配置如下:
upstream app_up {
server 192.168.0.5:8080;
server 192.168.0.6:8080;
}
server {
listen 80;
server_name www.zandili.com;
location / {
rewrite ^(.*)$ /app$1 break;
proxy_pass http://app_up;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
這樣我們訪問普通頁面如http://www.zandili.com/index.do是沒有問題的,nginx代理一切正常。
登入頁面地址http://www.zandili.com/admin/login.do
提交表單後服務端判斷使用者登入成功後redirect到http://www.zandili.com/admin/index.do
這個時候我們用Firefox的firebug檢視網路訪問,就會發現,轉向後的url地址為http://www.zandili.com/app/admin/index.do
目錄中多了一個app目錄,太意外了,app是後端tomcat下的目錄,竟然在redirect的時候傳遞到了客戶端,這不是我想要的。
此時更可怕的是如果程式裡設定了404錯誤頁,我們多了app目錄的訪問肯定找不到資源,就會無限重定向到404頁面......
為這個問題苦惱啊,難道要為此放棄redirect不成?
曾經一度的解決方法是把網站部署到webapps下的ROOT目錄,這樣就不會多一個目錄了(這是在逃避問題)。
仔細檢視firebug提供的資訊,發現這是個302重定向,多的這個app目錄我只能理解為http://www.zandili.com/admin/login.do在進行redirect的時候,根據絕對路徑獲取到的是http://192.168.0.5:8080/app/admin/index.do的路徑,nginx把這個跳轉地址替換域名和埠後傳遞給客戶端成http://www.zandili.com/app/admin/login.do這個地址重新發起請求,就出錯了(這也就理解了redirect為什麼是客戶端轉向)。
查了很多資料,一個字眼就頻頻出現,“proxy_redirect” ,這個在nginx裡到底是什麼作用?
NGINX的proxy_redirect功能比較強大,其作用是對傳送給客戶端的URL進行修改。
現在問題就出在傳送給客戶端的URL沒有修改成我們需要的路徑,看來這個有利於解決問題。
我們對nginx裡的配置稍加修改
upstream app_up {
server 192.168.0.5:8080;
server 192.168.0.6:8080;
}
server {
listen 80;
server_name www.zandili.com;
location / {
rewrite ^(.*)$ /app$1 break;
proxy_pass http://app_up;
proxy_redirect default;#這個可以不要了,留著也沒有啥危害
proxy_redirect http://www.zandili.com/app http://$host:$server_port;
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_redirect http://www.zandili.com/app http://$host:$server_port;
就是把服務端的跳轉指令中的url進行修改,我們把app目錄給抹掉再返回給客戶端,這樣就正常了。
看來還是有必要進一步學習下nginx的知識。