如何编写匹配 url /%ef 的 nginx 位置指令?

How can I write an nginx location directive that matches the url /%ef?

我想匹配 GET /%ef HTTP/1.1 这样的请求。所以我创建了这个配置:

location /%ef {
    return 400;
}

我用debug编译了nginx,做了curl -v 'localhost:8080/%ef'。我得到了 404 而不是我预期的 400。这是日志的相关部分:

2015/03/29 17:40:43 [debug] 48043#0: *5 http request line: "GET /%ef HTTP/1.1"
2015/03/29 17:40:43 [debug] 48043#0: *5 s:0 in:'2F:/'
2015/03/29 17:40:43 [debug] 48043#0: *5 s:1 in:'25:%'
2015/03/29 17:40:43 [debug] 48043#0: *5 s:4 in:'65:e'
2015/03/29 17:40:43 [debug] 48043#0: *5 s:5 in:'66:f'
2015/03/29 17:40:43 [debug] 48043#0: *5 s:1 in:'EF:ï'
2015/03/29 17:40:43 [debug] 48043#0: *5 http uri: "/ï"
2015/03/29 17:40:43 [debug] 48043#0: *5 http args: ""
2015/03/29 17:40:43 [debug] 48043#0: *5 http exten: ""
2015/03/29 17:40:43 [debug] 48043#0: *5 http process request header line
2015/03/29 17:40:43 [debug] 48043#0: *5 http header: "User-Agent: curl/7.37.1"
2015/03/29 17:40:43 [debug] 48043#0: *5 http header: "Host: localhost:8080"
2015/03/29 17:40:43 [debug] 48043#0: *5 http header: "Accept: */*"
2015/03/29 17:40:43 [debug] 48043#0: *5 http header done
2015/03/29 17:40:43 [debug] 48043#0: *5 event timer del: 4: 1427676103018
2015/03/29 17:40:43 [debug] 48043#0: *5 rewrite phase: 0
2015/03/29 17:40:43 [debug] 48043#0: *5 test location: "/"
2015/03/29 17:40:43 [debug] 48043#0: *5 test location: "50x.html"
2015/03/29 17:40:43 [debug] 48043#0: *5 using configuration "/"

因此,根据 2015/03/29 17:40:43 [debug] 48043#0: *5 http uri: "/ï" 行,nginx 将此请求与 /ï 匹配,这就是 url 解码后的 %ef。好的。我这样更新了配置:

location /%ef {
    return 400;
}
location /ï {
    return 400;
}

我重复了我的请求。现在我得到:

2015/03/29 17:37:48 [debug] 48018#0: *4 http request line: "GET /%ef HTTP/1.1"
2015/03/29 17:37:48 [debug] 48018#0: *4 s:0 in:'2F:/'
2015/03/29 17:37:48 [debug] 48018#0: *4 s:1 in:'25:%'
2015/03/29 17:37:48 [debug] 48018#0: *4 s:4 in:'65:e'
2015/03/29 17:37:48 [debug] 48018#0: *4 s:5 in:'66:f'
2015/03/29 17:37:48 [debug] 48018#0: *4 s:1 in:'EF:ï'
2015/03/29 17:37:48 [debug] 48018#0: *4 http uri: "/ï"
2015/03/29 17:37:48 [debug] 48018#0: *4 http args: ""
2015/03/29 17:37:48 [debug] 48018#0: *4 http exten: ""
2015/03/29 17:37:48 [debug] 48018#0: *4 http process request header line
2015/03/29 17:37:48 [debug] 48018#0: *4 http header: "User-Agent: curl/7.37.1"
2015/03/29 17:37:48 [debug] 48018#0: *4 http header: "Host: localhost:8080"
2015/03/29 17:37:48 [debug] 48018#0: *4 http header: "Accept: */*"
2015/03/29 17:37:48 [debug] 48018#0: *4 http header done
2015/03/29 17:37:48 [debug] 48018#0: *4 event timer del: 3: 1427675928222
2015/03/29 17:37:48 [debug] 48018#0: *4 rewrite phase: 0
2015/03/29 17:37:48 [debug] 48018#0: *4 test location: "/"
2015/03/29 17:37:48 [debug] 48018#0: *4 test location: "50x.html"
2015/03/29 17:37:48 [debug] 48018#0: *4 test location: "ï"
2015/03/29 17:37:48 [debug] 48018#0: *4 using configuration "/"

它仍然不符合我的位置。根据行 2015/03/29 17:37:48 [debug] 48018#0: *4 test location: "ï",我的新位置似乎以一种意想不到的方式被解释。

如何编写与 url /%ef 匹配的位置指令?

我试图匹配的其余路线是 /%EF%BF%BD。这是 replacement character 的 utf-8 字节表示。当我重写位置指令以实际包含替换字符本身时,nginx 匹配它:

location /� {
  return 400;
}