Nginx 通过代理重定向、重写和保留 URL

rob*_*cox 83 rewrite nginx proxy redirect

在 Nginx 中,我们一直在尝试重定向 URL,如下所示:

http://example.com/some/path -> http://192.168.1.24
Run Code Online (Sandbox Code Playgroud)

用户仍然可以在浏览器中看到原始 URL。一旦用户被重定向,假设他们点击链接到/section/index.html,我们希望它发出一个导致重定向的请求

http://example.com/some/path/section/index.html -> http://192.168.1.24/section/index.html
Run Code Online (Sandbox Code Playgroud)

并再次保留原始 URL。

我们的尝试涉及使用代理和重写规则的各种解决方案,下面显示了使我们最接近解决方案的配置(请注意,这是 Web 服务器的 Web 服务器配置example.com)。但是,这仍然存在两个问题:

  • 它没有正确执行重写,因为 Web 服务器收到的请求 URLhttp://192.168.1.24包含/some/path并因此无法提供所需的页面。
  • 提供页面后将鼠标悬停在链接上时,/some/pathURL 中缺少

    server {
        listen          80;
        server_name     www.example.com;
    
        location /some/path/ {
            proxy_pass http://192.168.1.24;
            proxy_redirect http://www.example.com/some/path http://192.168.1.24;
            proxy_set_header Host $host;
        }
    
        location / {
            index index.html;
            root  /var/www/example.com/htdocs;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

我们正在寻找一种仅涉及更改example.com. 我们可以更改192.168.1.24(也是 Nginx)上的配置,但是我们想尝试避免这种情况,因为我们需要为数百个通过 代理访问的不同服务器重复此设置example.com

Ale*_*Ten 70

您应该在proxy_pass指令中使用 URI 部分。此外,您混淆了proxy_redirect指令的顺序参数,可能您根本不需要它。Nginx 对此指令有合理的默认值。

在这种情况下,您的location块可能非常简单:

location /some/path/ {
    proxy_pass http://192.168.1.24/;
    # note this slash  -----------^
    proxy_set_header Host $host;
}
Run Code Online (Sandbox Code Playgroud)

  • 斜线对我有用。现在 mydomain.com/some/path/* 被正确代理到 192.168.1.24/* 而不是 192.168.1.24/some/path/* (11认同)
  • 我可以对此回复中的“# note this slash”评论点赞吗?为那条评论喝三声! (8认同)

Ter*_*nen 64

首先,您不应该root在 location 块内使用指令,这是一种不好的做法。在这种情况下,虽然没关系。

尝试添加第二个位置块:

location ~ /some/path/(?<section>.+)/index.html {
    proxy_pass http://192.168.1.24/$section/index.html;
    proxy_set_header Host $host;
}
Run Code Online (Sandbox Code Playgroud)

这将 /some/path/ 之后和 index.html 之前的部分捕获到 $section 变量,然后用于设置 proxy_pass 目标。如果需要,您可以使正则表达式更具体。

  • 浏览器看到的链接是由运行在 192.168.1.24 服务器上的软件生成的。您应该修改该软件以实现您想要的。 (8认同)

cns*_*nst 6

您可以使用以下配置/some/path/在前端和/后端之间进行100% 无缝映射。

请注意,这是迄今为止唯一可以无缝处理产生404 Not Found错误的绝对路径的答案,前提Referer是浏览器发送了正确的 HTTP标头,因此,所有这些 gif 都应该继续加载而无需修改底层 HTML (这不仅昂贵,而且在没有默认编译的附加模块的情况下也不支持)。

location /some/path/ {
    proxy_pass http://192.168.1.24/; # note the trailing slash!
}
location / {
    error_page 404 = @404;
    return 404; # this would normally be `try_files` first
}
location @404 {
    add_header Vary Referer; # sadly, no effect on 404
    if ($http_referer ~ ://[^/]*(/some/path|/the/other)/) {
        return 302 $1$uri;
    }
    return 404 "Not Found\n";
}
Run Code Online (Sandbox Code Playgroud)

您可以在https://github.com/cnst/StackOverflow.cnst.nginx.conf存储库中找到完整的概念验证和最小可行产品

这是一个测试运行,以确认所有边缘情况似乎都有效:

curl -v -H 'Referer: http://example.su/some/path/page.html' localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location
> GET /and/more.gif HTTP/1.1
> Referer: http://example.su/some/path/page.html
< HTTP/1.1 302 Moved Temporarily
< Location: http://localhost:6586/some/path/and/more.gif
< Vary: Referer

curl -v localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location
> GET /and/more.gif HTTP/1.1
< HTTP/1.1 404 Not Found

curl -v localhost:6586/some/path/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location -e uri
> GET /some/path/and/more.gif HTTP/1.1
< HTTP/1.1 200 OK
request_uri:    /and/more.gif
Run Code Online (Sandbox Code Playgroud)

PS。如果你有很多不同的路径映射,然后而不是做的比较正则表达式$http_referer内的if范围内location @404,你可能想使用基于全局的map指令来代替。

另请注意,根据相关答案, 中的尾随斜杠proxy_pass以及location包含在其中的斜杠非常重要

参考: