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

我正在尝试configurationnginx,以便可以通过两个不同的URL访问相同的静态内容, 而无需任何redirect。

例如,如果客户端在浏览器中input/path/to/A ,我想要检索与/path/to/B相同的内容。

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

例如:

 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 ,但我想这样做使用服务器configuration,而不是文件系统技巧。

我的问题是:

  1. 如何才能做到这一点?
  2. rewrite模块在什么情况下做内部redirect与发送30x代码给客户端? 我无法从文档中清楚地分辨出来。

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

编辑:这是一个真正的configuration, curl命令等:

首先,configuration:

 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结果相同)。

所以只有在第一种情况下,我会得到一个301redirect,虽然我的configuration从来没有明确提到这样的事情。

这是怎么回事?

nginxrewrite不会导致301状态(除非明确configuration),所以301可能是由nginxconfiguration的其他部分引起的。

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

这是显示目录索引的Web服务器的默认行为,例如Apache也是如此。 只要你请求“目录”,它就会把你redirect到“directory /”。

Apache的文档是明确的,例如https://httpd.apache.org/docs/2.4/mod/mod_dir.html&#x8BF4;

当服务器收到URL http:// servername / foo / dirname(其中dirname是目录)的请求时,会发出“尾部斜线”redirect。 目录需要一个尾部斜线,所以mod_dir发出一个redirect到http:// servername / foo / dirname / 。

看起来nginx的文档比较公平一点,比如http://nginx.org/en/docs/http/ngx_http_autoindex_module.html只是说&#xFF1A;

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

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

networking上还存在另外一个关于同一问题的问题: https : //stackoverflow.com/questions/15555428/nginx-causes-301-redirect-if-theres-no-trailing-slash

好的,经过一番实验,我发现了一些不同的解决scheme。

回顾一下,我希望/A在用户的浏览器中保持为/A (不redirect到/B ),但我仍然希望它显示/B的内容。

选项1:使用符号链接(:这可以工作,但需要访问文件系统。避免问题。

选项2:通过使用精确匹配( = )位置块来防止自动结尾斜杠301redirect:

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

我从Nginx文档中发现了这个:

没有结尾的斜杠,代码301的永久性redirect将被返回到所附的斜线所请求的URI。 如果不需要,可以定义URI和位置的精确匹配

选项3:使用从/A/A/的redirect,但手动执行,所以它不会以(重写)redirect到/B/返回给客户端:

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

我最终select3,因为它使/A行为就像/B ,包括尾部斜杠redirect(但现在正确的地方)。