重写重定向以包括用于访问服务的端口

时间:2015-05-08 20:13:15

标签: http redirect nginx

我有这样的设置:

enter image description here

使用我的Vagrant开发环境的用户访问其主机上的localhost:8080,然后将其转发到Vagrant,转发到运行于localhost:80客户端的NGINX。有些请求会转发到我在客户端localhost:8080运行的应用服务器,有些请求是NGINX提供的静态文件。

当我访问我的网站时,会发生奇怪的事情。我有一个登录页面,该页面在成功时重定向,并且URL从http://localhost:8080/login重写为http://localhost:80/login

这是我网站的NGINX配置:

upstream appserver {
    server 127.0.0.1:8080;
}

upstream production {
    server www.mysite.com:443;
}

server {
    listen 80 default_server;
    server_name _;

    client_max_body_size 20M;

    access_log /var/log/nginx/project.access.log;
    error_log /var/log/nginx/project.error.log;

    index /index;

    location ~ ^(/js/testpage.js) {
        alias   /vagrant/artifacts/www/js/testpage.js;
    }

    location ~ ^(/test/js/app.js) {
        alias   /vagrant/test/js/app.js;
    }

    location ~ /test/js/app_router.js {
        alias   /vagrant/test/js/app_router.js;
    }

    location ~ /test/js/app_layout_controller.js {
        alias   /vagrant/test/js/app_layout_controller.js;
    }

    location ~ /test/js/apps/navbar/sections/layout/navbar_layout_controller.js {
        alias   /vagrant/test/js/apps/navbar/sections/layout/navbar_layout_controller.js;
    }

    location ~ /test/js/apps/navbar/sections/navbar/navbar_options_view.js {
        alias   /vagrant/test/js/apps/navbar/sections/navbar/navbar_options_view.js;
    }

    location ~ /test/js/apps/navbar/sections/navbar_all_views.js {
        alias   /vagrant/test/js/apps/navbar/sections/navbar_all_views.js;
    }

    location ~ ^/test/js/apps/(.*/testpage_.*\.js)$ {
        alias   /vagrant/test/js/apps/$1;
    }

    location ~ ^/test/js/(.*)$ {
        alias /vagrant/js/$1;
    }

    location ~ ^/build/js/(.*)$ {
        alias /vagrant/artifacts/www/js/$1;
    }

    location ~ ^/build/css/(.*)$ {
        alias /vagrant/artifacts/www/css/$1;
    }

    location ~ ^/(.*main.*)\.[@\-_\/\d\w]+\.(js|css)$ {
        alias /vagrant/$1.$2;
    }

    location ~ ^/(css|js|fonts|favicon.ico) {
        root   /vagrant;
    }

    location ~ ^/receipts/js/(.*)$ {
        alias /vagrant/receipts/js/$1;
    }

    location ~ ^/bower_components/(.*)$ {
        alias /vagrant/bower_components/$1;
    }

    location ~ ^/login-promo/ {
        access_log off;
        proxy_pass https://production;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location ~ ^/(admin|login|logout|index|build|testpage|receipts|open|reset|resetpage|privacy|change|activeUser|personPrivacyAcceptances) {
        access_log off;

        proxy_pass http://appserver;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

我不确定重定向实际来自哪里,它可能来自应用服务器后端或来自前端JavaScript。有没有办法可以确保所有重定向都占用访问客户端使用的端口?

更新:只需在根页面添加<a href="/login">login</a>链接,然后尝试使用该链接进行导航,即可将我重定向到http://localhost:80/login而不是http://localhost:8080/login

3 个答案:

答案 0 :(得分:1)

这可能是将客人的nginx端口发送到主机上的另一个端口的不良副作用。

请参阅http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect

停用最后一个位置块中的代理重定向应该可以解决问题:

proxy_redirect off;

答案 1 :(得分:0)

由于port_in_redirect默认为on,可能会发生这种情况。请参阅:http://wiki.nginx.org/HttpCoreModule#port_in_redirect

禁用这可能会阻止一些混淆为什么端口被应用。

从那里开始,如果需要,在代理传递重定向中设置适当的host_portremote_port就很简单了。通过查看您的配置,您似乎习惯使用核心模块变量,包含这些变量将非常简单。

请参阅:

http://wiki.nginx.org/HttpCoreModule#.24remote_port http://wiki.nginx.org/HttpCoreModule#.24server_port

答案 2 :(得分:0)

这似乎是由于应用程序代码中的重定向错误造成的。

如果您具有与上述类似的体系结构并且遇到问题,则可能是您遇到问题的原因是由于尝试重定向而没有考虑Host标头。

你的nginx背后的应用程序会看到这样的请求:

GET /path/to/resource
Host: virtualinstance:8888

不幸的是,当它构造重定向时,它会做一些愚蠢的事情并重新构建重定向而不考虑Host标头,而是选择它知道它正在使用的主机和端口。破坏我的重定向的代码看起来像这样:

return redirect("http://" + getHostName() + "/" + getPath())

首先,它很难对协议进行硬编码,但更糟糕的是,它使用的方法在不考虑端口的情况下获取主机名。这会返回重定向到http://localhost/path,而不是http://localhost:8888/path

开发人员,这就是为什么您应该始终使用Host标头作为重定向的来源:

return redirect("%s://%s/%s" % (getProtocol(), getHeader("Host"), 
    getPath())

这使用原始协议,Host的全文和路径进行了理智的重定向。