web-dev-qa-db-ja.com

外部リンクURLエンコードは、Nginxサーバーで「%3F」および「%3D」につながります

サーバーに問題が発生しました。動的Webページのさまざまなサイトへの4つのインバウンドリンクがあり、次のようになっています。

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

それらは次のようになります。

myurl.com/default/Site?id=13

これらの%3F?記号のエスケープシーケンスであり、%3Dは等号のエスケープシーケンスであることを私は知っています。しかし、これらのリンクを使用すると、エラー400が発生します。それについて私は何ができますか?

4つのリンクは異なるサイト用であり、時間の経過とともにそのようなリンクが増えると思います。したがって、すべての修正が1つで完璧になります。

13
user3082653

まったく同じ質問が、約1年前に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ищетсяпоужераскодированномуадресу、очемвдокументациинаписано。

翻訳:

リクエストがそのような形式で届く場合、これらはもはや引数ではなく、リクエストされたファイルの名前です。もう1つのことは、文書化されているように、位置照合は正規化されたURIに対して実行されることです。

彼が提案した解決策は、ここSOでの質問のサンプル例に翻訳され、次のようになります。

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

location = /default/Site {
    [...]
}
8
cnst

次のサンプルは、URLに関係なく、すべての見栄えの悪いリクエスト(リクエストされたファイル名に?が含まれていると定義され、リクエストに%3Fとしてエンコードされている)をリダイレクトします。

(他の場所で正しくアドバイスされているように、そもそもこれらの誤った形式のリンクを取得するべきではないことに注意してください。それ以外の方法で誤った形式のリンクを修正できない場合にのみ、最後の手段として使用してください。このような要求は、有効なエージェントによって試行されます。)

server {
    listen      [::]:80;
    server_name localhost;

    rewrite     ^/([^?]*)\?(.*)$    /$1?$2?     permanent;
    location / {
        return  200 "id is $arg_id\n";
    }
}

これはどのように機能するかの例です—間違って見えるリクエストが検出されると、おそらく正しいLocation応答ヘッダーを持つ301 Moved Permanently応答で修正が試行され、ブラウザが自動的に再実行されます。 -新しく提供された場所にリクエストを発行します。

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
1
cnst

[〜#〜] url [〜#〜] は完全に有効です。そこに含まれるエスケープ文字は、エスケープされたものです。これはまったく問題ありません。

目的は、実際にはSiteではなくSite?id=13であり、残りはクエリ文字列であるリクエスト名(ほとんどの場合、ディスク上のファイル名に対応する)を持つことができることです。

これを必要とする文字をファイル名に含めるのは悪い習慣だと思います。ただし、URL引数では、それが必要になる場合があります。

それでも、リクエストURLは有効であり、おそらく希望どおりではありません。したがって、最初に誰かが間違ったURLを取得した場合は、エラーを修正する必要があることを示唆しています。

なぜエラー400が発生するのかよくわかりません。むしろエラー404が表示されるはずです。しかし、それはセットアップによって異なります。

また、特にnginxの場合、URL全体とURL部分を複数のレベルに渡して渡すこと(たとえば、リバースプロキシ、URLからの正規表現の照合、変数としての使用など)で、このようなエラーが発生する場合もあります。ただし、これを確認して修正するには、セットアップについて詳しく知る必要があります。

0
The Surrican