我运行一个提供静态文件的Nginx服务器。一些文件名包含诸如%3a
之类的字符串。
/var/www/testfile%3a
如果我尝试请求这些文件,则会出现 404 Not Found 错误。
这似乎是因为nginx decodes the URL并将%3a
替换为:
,然后找不到名为/var/www/testfile:
的文件。我从nginx的以下调试输出中推断出这一点:
2018/06/21 10:03:21 [debug] 32523#0: *6 http process request line
2018/06/21 10:03:21 [debug] 32523#0: *6 http request line: "GET /testfile%3a HTTP/1.1"
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'2F:/'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:1 in:'74:t'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'65:e'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'73:s'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'74:t'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'66:f'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'69:i'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'6C:l'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'65:e'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'25:%'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:4 in:'33:3'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:5 in:'61:a'
2018/06/21 10:03:21 [debug] 32523#0: *6 s:0 in:'3A::'
2018/06/21 10:03:21 [debug] 32523#0: *6 http uri: "/testfile:"
到目前为止,我想出了两种可能的解决方案:
%3a
成为文件名中的:
,并教育每个在此处上传文件的人。%
符号转为%25
。但是我相信重写阶段是在URL已经被解码之后进行的。当前,文件名中没有未转义的:
字符,因此我可以将:
重写为%253a
,这可能会起作用。尽管这些文件名中可能存在其他字符,但这是不可能的,因为它们可能以编码和未编码形式出现在URL中。 我认为可能有一个我忽略的更简单的解决方案。有没有办法告诉nginx从字面上对待每个URL,例如没有解码转义字符?
答案 0 :(得分:1)
目前,我已使用以下重写规则解决了该问题:
rewrite ^(.*):(.*)$ $1%3a$2 last;
重写URL后,似乎没有更多解码步骤了,因此:
可以直接替换为%3a
。
答案 1 :(得分:1)
如果您的网址中有百分号,只需将您的请求中的百分号与%25交换,如下所示:
https://domain/testfile%253a
然后它变成文件https://domain/testfile%3a
。
问题不在于“ Nginx解码URI”-您试图避开根据RFC标准的普通URI的工作方式,其中百分号始终用于编码特殊字符。您可能会读懂article about percent encoding并避免使用URI中使用的所有特殊字符,因为使用这些特殊字符都会引起问题(诸如?,&,#等字符,以及更多的字符)。对于文件名,完全避免使用它们是有意义的,例如,将它们替换为另一个字符,例如_。