我正在尝试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,而不是文件系统技巧。
我的问题是:
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从来没有明确提到这样的事情。
这是怎么回事?
在nginx中rewrite不会导致301状态(除非明确configuration),所以301可能是由nginxconfiguration的其他部分引起的。
rewrite是实现你想要的正确的方式,你的方法是正确的。
这是显示目录索引的Web服务器的默认行为,例如Apache也是如此。 只要你请求“目录”,它就会把你redirect到“directory /”。
Apache的文档是明确的,例如https://httpd.apache.org/docs/2.4/mod/mod_dir.html说
当服务器收到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只是说:
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(但现在正确的地方)。