浏览器url默认将unicode字符编码为%##.
但是,我可以通过CURL发出请求,http://localhost:8080/?而nginx将路径视为" ?".这怎么可能?Nginx是否允许在其路径中使用任意unicode?
例如,使用此配置,我可以设置一个额外的标头,以查看nginx看到了什么:
location ~* "(*UTF8)([^\w/\.\-\\% ])" {
add_header "response" $1;
return 200;
}
Run Code Online (Sandbox Code Playgroud)
请求:
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /? HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
* Server nginx/1.4.6 (Ubuntu) is not blacklisted
< Server: nginx/1.4.6 (Ubuntu)
< Date: Tue, 20 Jan 2015 21:44:51 GMT
< Content-Type: application/octet-stream
< Content-Length: 0
< Connection: keep-alive
< response: ? <--- SEE THIS?
<
* Connection #0 to host localhost left intact
Run Code Online (Sandbox Code Playgroud)
但是,当我删除UTF8标记时,标题包含"?" 好像nginx无法理解字符(或只是读取第一个字节).
location ~* "([^\w/\.\-\\% ])" {
add_header "response" $1;
return 200;
}
Run Code Online (Sandbox Code Playgroud)
请求:
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /? HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
* Server nginx/1.4.6 (Ubuntu) is not blacklisted
< Server: nginx/1.4.6 (Ubuntu)
< Date: Tue, 20 Jan 2015 21:45:35 GMT
< Content-Type: application/octet-stream
< Content-Length: 0
< Connection: keep-alive
< response: ?
<
* Connection #0 to host localhost left intact
Run Code Online (Sandbox Code Playgroud)
注意:更改此非utf-8正则表达式以捕获一个或多个 ([^...]+)也导致response: ?标头被发送(字节与多字节字符串?)
将正则表达式匹配记录到文件会导致请求条目如下:
GET /\xE4\xB8\x8E HTTP/1.1
Run Code Online (Sandbox Code Playgroud)
nwe*_*hof 13
除了正则表达式和终端配置之外,这与Unicode没有任何关系.对你的问题的简短回答是:nginx不关心Unicode编码,但它接受URL中的非ASCII字节.
这是解释您所看到的内容的长答案.如果输入命令
curl http://localhost:8080/?
Run Code Online (Sandbox Code Playgroud)
并且您的终端使用UTF-8作为编码,它将字符与(U + 4E0E)编码为三字节UTF-8序列
0xE4 0xB8 0x8E
Run Code Online (Sandbox Code Playgroud)
curl显然在URL中接受非ASCII字节,尽管它们在技术上是非法的.然后它将发送带有这些非ASCII字节的HTTP请求.由于没有默认的方式来显示这些字节,因此我将使用粗体C风格的十六进制转义符,如\ x00,从现在开始代表它们.所以发送的请求行curl看起来像:
GET/\ xE4\xB8\x8E HTTP/1.1
这是第一个之后的三个字节/.如果您查看日志的终端也支持UTF-8,则会在屏幕上显示为
GET /与HTTP/1.1
但这并不意味着您的HTTP请求中有Unicode字符.在HTTP级别,我们只处理字节.
nginx似乎也乐于接受URL中的非ASCII字节.然后是以下正则表达式
(*UTF8)([^\w/\.\-\\% ])
Run Code Online (Sandbox Code Playgroud)
在UTF-8模式下工作将字节序列\ xE4\xB8\x8E视为匹配的字符\w,因此标题将是
响应:\ xE4\xB8\x8E
你的终端显示为
回应:与
另一方面,正则表达式
([^\w/\.\-\\% ])
Run Code Online (Sandbox Code Playgroud)
直接在字节上工作,因此它只匹配路径的第一个字节,或者根本不匹配.由于某种原因,它认为序列的第一个字节\ xE4\xB8\x8E匹配\w(可能是因为它假定为Latin1或Windows-1252字符串),因此标题将为:
回复:\ xE4
您的终端决定显示为
回应:?
因为字节\ xE4后跟换行符是无效的UTF-8.正则表达式([^\w/\.\-\\% ])+匹配整个字节序列,因此它产生与UTF-8正则表达式相同的结果.
如果你看到类似的东西
GET /\xE4\xB8\x8E HTTP/1.1
Run Code Online (Sandbox Code Playgroud)
在您的日志中,这是因为日志代码的作者决定将转义序列用于非ASCII字节.一般来说,这是一个好主意,因为无论终端配置如何,它总是产生相同的输出,并且真正显示正在发生的事情:您的HTTP请求只包含非ASCII字节.
| 归档时间: |
|
| 查看次数: |
4408 次 |
| 最近记录: |