Nginx:从多个 URL 访问相同的内容

Nginx:从多个 URL 访问相同的内容

我正在尝试配置 nginx,以便可以通过两个不同的 URL 访问相同的静态内容没有任何重定向。

例如,如果客户端/path/to/A在其浏览器中输入,我希望它检索与相同的内容/path/to/B

我尝试使用rewrite,但在这种情况下 Nginx 似乎给我一个 301 重定向。

例如:

server {
    root /my/www/data;

    rewrite ^/path/to/A(.*)$ /path/to/B$1;
    # Note: /my/www/data/path/to/B *does* actually exist on disk.
    # However, the .../A version does not.
}

我猜想实现这一点的一种方法是使用符号链接/my/www/data/A指向/my/www/data/B,但我试图使用服务器配置而不是文件系统技巧来做到这一点。

我的问题是:

  1. 如何才能做到这一点?
  2. 在什么情况下rewrite模块会进行内部重定向,而不是向客户端发送 30x 代码?我无法从文档中清楚地看出。

注意:这与另一个问题非常相似:Nxginx 重写 URL 而不进行重定向 但是,那个不是很详细。

编辑:这是一个真实的配置,包含curl命令等:

首先,配置:

server {

    root /usr/share/nginx/www/mydata;
    index index.html index.htm;

    # Make site accessible from http://localhost/
    server_name localhost;

    location / {
        try_files $uri $uri/ =404;
    }

    rewrite_log on;    
    rewrite ^/A(.*)$ /B$1 last;
}

现在,我的网络根目录内容:

$ find /usr/share/nginx/www/mydata/
/usr/share/nginx/www/mydata/
/usr/share/nginx/www/mydata/B
/usr/share/nginx/www/mydata/B/index.html
/usr/share/nginx/www/mydata/index.html

运行之后,我得到了以下结果curl

$ curl -i 'http://localhost/A'
HTTP/1.1 301 Moved Permanently
Server: nginx/1.2.1
...
Location: http://localhost/B/
...
<snipped>

不过,我确实注意到/A/(带有尾部斜杠)并且/A/index.html工作正常:

$ curl -i 'http://localhost/A/'
HTTP/1.1 200 OK
Server: nginx/1.2.1
<snip - I see data for B/index.html, as I expect>

( 结果相同/A/index.html)。

因此,只有在第一种情况下我才会得到 301 重定向,尽管我的配置从未明确提到这样的事情。

这是怎么回事?

答案1

rewrite通常nginx不会导致 301 状态(除非明确配置),因此 301 可能是由nginx配置的其他部分引起的。

rewrite是实现您想要的正确方法,您的方法是正确的。

答案2

这是显示目录索引的 Web 服务器的默认行为,例如 Apache 也是如此。每当您仅请求“directory”时,它都会将您重定向到“directory/”之类的位置。

Apache 文档对此有明确说明,例如https://httpd.apache.org/docs/2.4/mod/mod_dir.html

当服务器收到 URL 请求时,会发出“尾部斜杠”重定向http://服务器名称/foo/目录名称其中 dirname 是目录。目录需要尾部斜杠,因此 mod_dir 发出重定向到http://服务器名称/foo/目录名称/

似乎 Nginx 文档对此比较含糊,例如http://nginx.org/en/docs/http/ngx_http_autoindex_module.html只是说:

ngx_http_autoindex_module 模块处理以斜杠字符 ('/') 结尾的请求并生成目录列表。通常,当 ngx_http_index_module 模块找不到索引文件时,请求会被传递给 ngx_http_autoindex_module 模块。

它没有解释前面的步骤,请求如何以斜线结尾,这似乎是隐含的。

网络上还有另一个关于同一问题的老问题:https://stackoverflow.com/questions/15555428/nginx-causes-301-redirect-if-theres-no-trailing-slash

答案3

好的,经过一些实验,我找到了一些不同的解决方案。

总而言之,我想/A/A在用户的浏览器中(不重定向到/B),但我仍然希望它显示来自的内容/B

选项1:使用符号链接(:这可行,但您需要访问文件系统。回避该问题。

选项 2:=使用精确匹配 ( ) 位置块来防止自动尾部斜杠 301 重定向:

location = /A {
    rewrite "" /B/;
}
# Note: the below should probably be inside a location block.
rewrite ^/A(.+)$ /B$1 last;

我从Nginx 文档

如果没有尾部斜杠,则将返回带有代码 301 的永久重定向到附加了斜杠的请求 URI。如果不希望这样,可以定义 URI 和位置的精确匹配

选项 3:/A使用从到 的重定向/A/,但要手动执行,这样它就不会作为到 的(重写)重定向返回给客户端/B/

location = /A {
    return 301 /A/;
}
location /A/ {
    rewrite ^/A/(.*)$ /B/$1 last;
}

我最终选择了选项 3,因为它的/A行为就像/B,包括尾随斜杠重定向(但现在到正确的位置)。

相关内容