nginx反向代理tomcat应用,struts2网站程序redirect时导致请求地址错误的解决方法

时间:2023-03-08 16:51:22

一个使用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的知识。