我的服务器出了问题。我有四个到动态网页不同网站的入站链接,如下所示:
myurl.com/default/Site%3Fid%3D13
他们应该是这样的:
myurl.com/default/Site?id=13
我知道那些%3F
是?
符号的转义序列,%3D
是等号的转义序列。但是当我使用这些链接时,我确实收到错误400。我该怎么办?
这四个链接适用于不同的网站,我想随着时间的推移会有更多这样的链接。因此,对所有人的一个解决方案将是完美的。
答案 0 :(得分:8)
大约一年前,nginx-ru邮件列表上确实提出了一个完全相同的问题:
http://mailman.nginx.org/pipermail/nginx-ru/2013-February/050200.html
最有帮助的回应,由Nginx,Inc,员工/开发人员,ВалентинБартенев:
http://mailman.nginx.org/pipermail/nginx-ru/2013-February/050209.html
Еслизапросприходитвтакомвиде,тоэтоуженепараметры,аимязапрошенного файла。 Другоедело,чтоlocationищетсяпоужераскодированномуадресу,очемв документациинаписано。
翻译:
如果请求以这种形式出现,那么这些不再是args,而是请求文件的名称。另一件事是,如文档所述,位置匹配是针对规范化的URI执行的。
他建议的解决方案,从SO的问题翻译成示例,然后是:
location /default/Site? {
rewrite \?(.*)$ /default/Site?$1? last;
}
location = /default/Site {
[...]
}
答案 1 :(得分:1)
以下示例将重定向所有看似错误的请求(在请求的文件名中定义为?
- 在请求中编码为%3F
),不管URL如何,都会重定向到看起来不那么错误的请求。 / p>
(请注意,正如在其他地方正确建议的那样,您不应该首先获得这些错误形成的链接,因此,将其作为最后手段使用 - 只有当您无法纠正错误形成的链接时,否则,请注意,有效代理会尝试此类请求。)
server {
listen [::]:80;
server_name localhost;
rewrite ^/([^?]*)\?(.*)$ /$1?$2? permanent;
location / {
return 200 "id is $arg_id\n";
}
}
这是它如何工作的示例 - 当遇到错误查看的请求时,使用301 Moved Permanently
响应进行更正尝试,并使用假定正确的Location
响应标头,这将使浏览器成为可能自动将请求重新发送到新提供的位置:
opti# curl -6v "http://localhost/default/Site%3Fid%3D13"
* About to connect() to localhost port 80 (#0)
* Trying ::1...
* connected
* Connected to localhost (::1) port 80 (#0)
> GET /default/Site%3Fid%3D13 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.4.1
< Date: Wed, 15 Jan 2014 17:09:25 GMT
< Content-Type: text/html
< Content-Length: 184
< Location: http://localhost/default/Site?id=13
< Connection: keep-alive
<
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.4.1</center>
</body>
</html>
* Connection #0 to host localhost left intact
* Closing connection #0
请注意,不会对正确的请求进行更正尝试:
opti# curl -6v "http://localhost/default/Site?id=13"
* About to connect() to localhost port 80 (#0)
* Trying ::1...
* connected
* Connected to localhost (::1) port 80 (#0)
> GET /default/Site?id=13 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.4.1
< Date: Wed, 15 Jan 2014 17:09:30 GMT
< Content-Type: application/octet-stream
< Content-Length: 9
< Connection: keep-alive
<
id is 13
* Connection #0 to host localhost left intact
* Closing connection #0
答案 2 :(得分:0)
URL完全有效。它包含的转义字符只是逃脱的。这完全没问题。
目的是你实际上可以有一个请求名称(在大多数情况下对应于磁盘上的文件名)Site?id=13
而不是Site
,其余的作为查询字符串。
我认为在文件名中包含字符会使这一点成为必要,这是不好的做法。但是,在URL参数中,它可能是必要的。
然而,请求URL是有效的,可能不是您想要的。因此,建议您在任何人首先获取错误的URL时纠正错误。
我真的不明白为什么你会收到错误400;你应该得到一个错误404.但这取决于你的设置。
还有一些情况,特别是对于nginx,主要涉及沿多个级别传递整个URL和URL部分(例如反向代理,匹配URL中的正则表达式并将它们用作变量等),这样的错误可能导致。但要验证并修复它,我们需要了解有关您的设置的更多信息。