URL 结尾和 nginx 重写规则

URL 结尾和 nginx 重写规则

我正在使用以下 nginx 重写规则,但我不明白为什么会出现以下结果。

server {
    server_name old.example.com;
    listen 80;
    listen [::]:80;
    rewrite ^/.*-f(\d+)/.*-t(\d+)\.html$ https://new.example.com/view.php?f=$1&t=$2 permanent;
}

以下结果是正常的(url 以‘.html’结尾)。

$ curl --head "http://old.example.com/abcd-f15/efgh-t125.html"
HTTP/1.1 301 Moved Permanently
Server: nginx/1.17.6
Date: Sat, 02 May 2020 12:48:53 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://new.example.com/view.php?f=15&t=125

以下结果也是可以的(url 不以“.html”结尾)。

$ curl --head "http://old.example.com/abcd-f15/efgh-t125.htmlx"
HTTP/1.1 404 Not Found
Server: nginx/1.17.6
Date: Sat, 02 May 2020 12:50:26 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

但是我不明白以下结果(url 不以 '.html' 结尾,但重写规则匹配)。

$ curl --head "http://old.example.com/abcd-f15/efgh-t125.html#x"
HTTP/1.1 301 Moved Permanently
Server: nginx/1.17.6
Date: Sat, 02 May 2020 12:51:53 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://new.example.com/view.php?f=15&t=125

答案1

让我们来看看RFC 3986,3关于 URL 语法:

     foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment
      |   _____________________|__
     / \ /                        \
     urn:example:animal:ferret:nose

我们感兴趣的是分段,它的定义在第 3.5 节

片段标识符在信息检索系统中发挥着特殊作用,是客户端间接引用的主要形式,允许作者明确标识现有资源中仅由资源所有者间接提供的方面。因此,片段标识符不用于 URI 的特定方案处理;相反,片段标识符在取消引用之前与 URI 的其余部分分离,因此片段本身内的标识信息仅由用户代理取消引用,而与 URI 方案无关。

TL;DR: HTTP URL 的处理分段 #x仅发生在客户端。

让我们用curla添加一些详细内容-v,这样我们就可以更清楚地看到这一点:

$ curl --head "http://old.example.com/abcd-f15/efgh-t125.html#x"

> HEAD /abcd-f15/efgh-t125.html HTTP/1.1
> Host: old.example.com
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.17.6
< Date: Sat, 02 May 2020 12:51:53 GMT
< Content-Type: text/html
< Content-Length: 169
< Connection: keep-alive
< Location: https://new.example.com/view.php?f=15&t=125

我相信从中您已经可以推断出为什么这是您预期的行为rewrite


重定向后片段会发生什么?除非你的Location:头部专门指定了一个新的片段,否则客户端(网络浏览器)会保留它RFC 7231, 7.1.2

如果(重定向)响应Location中提供的值3xx没有片段组件,则用户代理必须处理重定向,就好像该值继承了用于生成请求目标的 URI 引用的片段组件(即,重定向继承原始引用的片段,如果有)。

简而言之,对于 URL http://old.example.com/abcd-f15/efgh-t125.html#x

  • 如果Location没有指定新的片段(当前情况):

      > GET /abcd-f15/efgh-t125.html
      > Host: old.example.com
      < Location: https://new.example.com/view.php?f=15&t=125
    

    ->https://new.example.com/view.php?f=15&t=125#x

  • y如果您在规则中添加了片段rewrite

      > GET /abcd-f15/efgh-t125.html
      > Host: old.example.com
      < Location: https://new.example.com/view.php?f=15&t=125#y
    

    ->https://new.example.com/view.php?f=15&t=125#y

  • 新的 HTTP 请求也不包含片段,因此两者相同:

      > GET /view.php?f=15&t=125
      > Host: new.example.com
    

相关内容