13

我的服务器有问题。我有四个指向动态网页不同站点的入站链接,如下所示:

myurl.com/default/Site%3Fid%3D13

它们应该如下所示:

myurl.com/default/Site?id=13

我确实知道那些%3F是符号的转义序列,?并且%3D是等号的转义序列。但是当我使用这些链接时,我确实收到了错误 400。我能做些什么呢?

这四个链接用于不同的站点,我想随着时间的推移会有更多这样的链接。因此,所有人的解决方案将是完美的。

4

3 回答 3

9

大约一年前,在 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 ищется по уже раскодированному адресу, о чем в документации написано。

翻译:

如果请求以这种形式出现,那么这些不再是参数,而是请求文件的名称。另一件事是,如文件所述,位置匹配是针对规范化的 URI 执行的。

他建议的解决方案,从这里的问题翻译为示例示例,然后将是:

location /default/Site? {
    rewrite \?(.*)$ /default/Site?$1? last;
}

location = /default/Site {
    [...]
}
于 2014-01-09T05:34:14.073 回答
1

以下示例将所有看起来错误的请求(定义为?在请求的文件名中具有 - 在请求中编码%3F)重定向到看起来不太错误的请求,而不考虑 URL。

(请注意,正如其他地方正确建议的那样,您不应该首先获得这些格式错误的链接,因此,将其用作最后的手段 - 只有当您无法纠正格式错误的链接时,您才知道此类请求由有效代理尝试。)

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
于 2014-01-15T17:17:17.657 回答
0

URL完全有效。它包含的转义字符就是这样,转义。这很好。

目的是您实际上可以有一个请求名称(在大多数情况下对应于磁盘上的文件名),它是Site?id=13和不是Site,其余的作为查询字符串。

我认为在文件名中有必要的字符是不好的做法。但是,在 URL 参数中,这很可能是必要的。

尽管如此,请求 URL 是有效的,但可能不是您想要的。因此,这建议您应该更正错误,只要有人首先选择了错误的 URL。

我真的不明白为什么您会收到错误 400;你应该得到一个错误 404。但这取决于你的设置。

还有一些情况,尤其是 nginx,主要涉及沿多个级别传递整个 URL 和 URL 部分(例如反向代理、匹配来自 URL 的正则表达式并将它们用作变量等),其中可能会发生此类错误。但要验证这一点并修复它,我们需要更多地了解您的设置。

于 2014-01-15T16:10:39.010 回答