web-dev-qa-db-ja.com

URLの「%25」を書き換える方法

私のウェブサイトソフトウェアは、URLのスペース文字を「+」文字に置き換えます。適切なリンクは「 http://www.schirmacher.de/display/INFO/How+to+reattach+a+disk+」のようになります。 to + XenServer 'たとえば。

一部のウェブサイトはその記事にリンクしていますが、どういうわけかそれらの埋め込みエディターはエンコードを処理できないため、httpdログファイルに実際に表示されるのは

GET /display/INFO/How%2525252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer

もちろん、これは404エラーにつながります。 '+'文字は '%2b'としてエンコードされ、次に '%'文字は '%25'としてエンコードされているようです-数回。

さまざまなウェブサイトのさまざまなページへのそのような参照がたくさんあるので、訪問者が正しいページを取得できるようにURLを書き直したいと思います。

これがうまくいかない私の試みです:

RewriteRule ^(.*)%25(.*)$ $1%$2 [R=301]

それがすることになっていることは:%25文字列の前と後のすべてを取り、それらの文字列の間に '%'を入れて連結してからリダイレクトします。

サンプルの入力URLを使用すると、ルールは次のように書き換える必要があります。

/display/INFO/How%25252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer

リダイレクトが続くと、次のように書き換える必要があります

/display/INFO/How%252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer

そして再び

/display/INFO/How%2bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer

等々。最後に、多くのリダイレクトの後、私は去るべきでした

/display/INFO/How%2bto%2breattach%2ba%2bdisk%2bto%2bXenServer

これは、/ display/INFO/How + to + reattach + a + disk + to + XenServerと同等の有効なURLです。

私の問題は、式がまったく一致しないため、%25の1つのオカレンスを置き換えることすらできないことです。

リダイレクトの数には制限があることを理解しています。実際には[N]フラグを使用する必要がありますが、最初のステップを正しく行うことすらできません。


@ベンリー:あなたの詳細な答えをありがとう。私は今その問題に数時間を費やしました。これが私が見つけたものです:

  1. URL内の「%25」文字列は、mod_rewriteが認識する前に「%」に変換されます。したがって、RewriteRule ^(。)%25(。)$はURLの '%25'と一致せず、実際には '%2525'と一致します。

  2. バックスラッシュが存在しても違いはありません。私の場合、 '%'記号は後方参照として解釈されないようです。おそらくRewriteCondステートメントが前にないためです。しかし、念のために、それを使用する方がおそらく良いでしょう。

  3. [L、R = 301]の行が正しくありません。 %2bが一致するたびにリダイレクトを試みますが、許可されるリダイレクトには制限があり、それ以上ある場合は失敗します。

これが私が使っているmod_rewrite行です:

RewriteRule ^(.*)\%25(.*\%25.*)$ $1%$2 [N]
RewriteRule ^(.*)\%25(.*)$ $1%$2 [R=301,L]

RewriteRule ^(.*)\%2b(.*\%2b.*)$ $1+$2 [N]
RewriteRule ^(.*)\%2b(.*)$ $1+$2 [R=301,L]

3行目では、1つを除くすべての%2bシーケンスを「+」文字に置き換えます。 %2bシーケンスが1つしか残っていない場合、4行目が一致し、リダイレクトが強制されます。

1行目と2行目は基本的に同じですが、%25シーケンスです。 mod_proxy/mod_jkも使用しているため、可能な文字シーケンスごとに[R]フラグの付いたルールを設定する必要があります。リダイレクトにより、結果のURLが各モジュールに再度送信されます。そうしないと、httpdがディスクからURLを取得しようとし、私の場合は失敗します。

4
nn4l

これが元のルールで、「最後」を示すために[L]が追加されています。

RewriteRule ^(.*)%25(.*)$ $1%$2 [L,R=301]

その後、ここにいくつかの問題があります。まず、RewriteRuleパターンのパーセント記号には特別な意味があります。それらは、RewriteCondへの後方参照の始まりを示します。 (バックスラッシュを使用して)それらをエスケープすることで、これを回避できます。

RewriteRule ^(.*)\%25(.*)$ $1%$2 [L,R=301]

次に、%を置換に挿入しても、それはuriエンコードされた部分の一部として扱われません。これは、文字通りのパーセント記号に変換されます。受け取った元のURLでは、最初の%25"もリテラルのパーセント記号に変換されます。したがって、上記のルールは、%25または%2bに解決するのではなく、URLでリテラル%sまたはリテラル+になります。したがって、これらを手動で解決する必要があります。

RewriteRule ^(.*)\%25(.*)$ $1%$2
RewriteRule ^(.*)\%2b(.*)$ $1+$2 [L,R=301]

最後に、最初の25の後に%が1つだけではなく、多数ある可能性があるため、[N]を使用して「次へ」を示します。これは基本的に「プロセスを最初からやり直すが、新しいURLを入力として使用する」ことを意味します。したがって、これはパーセントの後の任意の数の25を処理します。

RewriteRule ^(.*)\%25(.*)$ $1%$2 [N]
RewriteRule ^(.*)\%2b(.*)$ $1+$2 [L,R=301]

注:これは、通常のApache構成でルールを設定する場合に機能します。 .htaccessとして設定する場合、正規表現に対してチェックされる文字列から先頭のスラッシュが省略されます。この場合、スラッシュを自分で追加し直す必要があります。

RewriteRule ^(.*)\%25(.*)$ /$1%$2 [N]
RewriteRule ^(.*)\%2b(.*)$ /$1+$2 [L,R=301]

更新:現在テストする機能はありませんが、ドキュメントを見ると、「エスケープなし」のオプションNEが表示され、結果の通常のエンコードマーカーとしてパーセントが機能します。私が正しく理解していれば、それはルールを次のように単純化できることを意味します。

RewriteRule ^(.*)\%25(.*)$ $1%$2 [NE,N,L,R=301]

しかし、繰り返しになりますが、これはテストされておらず、実際にNEフラグを使用したことがないため、誤解している可能性があります。これをテストして機能することがわかった場合は、お知らせください。このUPDATEを削除し、上記の回答を修正して、この単純なバージョンを含めます。

3
Ben Lee