タグ付けシステム用のきれいなURLとすべての特殊文字が必要です:+
、&
、#
、%
、および=
。リンクを二重にエンコードすることなくmod_rewriteでこれを行う方法はありますか?
Delicious.comとstackoverflowは、単独でエンコードされた特殊文字を処理できるようだと思います。魔法の式は何ですか?
私がやりたいことの例は次のとおりです。
http://www.foo.com/tag/c%2b%2b
次のRewriteRuleをトリガーします。
RewriteRule ^tag/(.*) script.php?tag=$1
タグの値は「c ++」になります
Apache/mod_rewriteの通常の操作は、プラス記号をスペースに変換するように見えるため、このようには機能しません。プラス記号を '%252B'にダブルエンコードすると、目的の結果が得られます-ただし、URLが乱雑になり、かなりハッキングされているように見えます。
Apache/mod_rewriteの通常の操作は、プラス記号をスペースに変換するように見えるため、このようには機能しません。
私はそれが全く起こっているとは思わない。 Apacheは、パス部分で%2Bを+ sにデコードしています。これは、+が有効な文字であるためです。 mod_rewriteがリクエストを見る前にこれを行います。
そのため、mod_rewriteはリクエスト「/ tag/c ++」を「script.php?tag = c ++」に変更します。ただし、application/x-www-form-encoded形式のクエリ文字列コンポーネントでは、エスケープ規則はパス部分に適用される規則とはわずかに異なります。特に、「+」はスペースの省略形です(「%20」と同じようにエンコードできますが、これは今では変更できない古い動作です)。
そのため、PHPのフォーム読み取りコードは 'c ++'を受け取り、それをC-space-spaceとして_GETにダンプします。
これを回避する方法は、書き換えフラグ「B」を使用することです。 http://httpd.Apache.org/docs/2.2/mod/mod_rewrite.html#rewriteflags を参照してください-奇妙なことに、多かれ少なかれ同じ例を使用しています!
RewriteRule ^tag/(.*)$ /script.php?tag=$1 [B]
私はあなたが何を求めているのか理解していないが、ApacheのNE
ディレクティブのRewriteRule
(noescape)フラグは興味があるかもしれない。基本的に、_mod_rewrite
_が、指定した置換パターンの特殊文字を自動的にエスケープしないようにします。 Apache 2.2ドキュメントに記載されている例は次のとおりです。
_RewriteRule /foo/(.*) /bar/arg=P1\%3d$1 [R,NE]
_
これにより、たとえば_/foo/zed
_が_/bar/arg=P1%3dzed
_へのリダイレクトに変換され、スクリプト_/bar
_がarg
という名前のクエリパラメーターと値_P1=zed
_、_PATH_INFO
_を見ると(大丈夫、それはrealクエリパラメータではないので、私を訴えます;-P)。
少なくとも、私はそれがどのように機能するかと思います。 。 。私はその特定のフラグを自分で使用したことはありません。
Urlに+サインを付けたmod_rewriteでも同様の問題に遭遇します。以下のようなシナリオ:
_http://deskdomain/2013/08/09/a+b+c.html
_のような書き換えが必要な+記号付きのURLがあります
RewriteRule ^/(.*) http://mobiledomain/do/urlRedirect?url=http://%{HTTP_Host}/$1
StrutsアクションurlRedirectはurlパラメーターを取得し、何らかの変更を行い、そのURLを別のリダイレクトに使用します。ただし、req.getParameter( "url")では、+記号が空に変わり、パラメーターurlの内容が_http://deskdomain/2013/08/09/a b c.html
_になり、リダイレクト404が見つかりません。それを解決するために(事前の回答からヘルプを得る)、書き換えフラグB(エスケープ逆参照)、およびNE(エスケープなし)を使用します。
RewriteRule ^/(.*) http://mobiledomain/do/urlRedirect?url=http://%{HTTP_Host}/$1 [B,NE]
Bは+から%2Bにエスケープし、NEはmod_writeエスケープ%2Bから%252B(二重エスケープ+記号)を防ぐため、req.getParameter("url")=http://deskdomain/2013/08/09/a+b+c.html
で
その理由は、req.getParameter( "url")がエスケープを解除し、+記号が空にならないことが原因だと思います。エスケープ解除%2Bを1回+に試してから、エスケープ解除+をもう一度空にできます。
_"%2B" unescape-> "+" unescape-> " "
_
根本的な問題は、1つのエンコード(具体的にはプラス記号はプラス記号)を持つリクエストから、異なるエンコード(プラス記号はスペースを表す)を持つリクエストに移行することです。解決策は、mod_rewriteが行うデコードをバイパスし、パスを生のリクエストからクエリ文字列に直接変換することです。
書き換えルールの通常のフローをバイパスするには、生のリクエスト文字列を環境変数に直接ロードし、通常の書き換えパスの代わりに環境変数を変更します。既にエンコードされているため、クエリ文字列に移動するときにエンコードを心配する必要は通常ありません。ただし、必要なのは、スペースではなくプラス記号として適切に中継されるように、プラス記号をパーセントエンコードすることです。
ルールは非常にシンプルです:
RewriteEngine On
RewriteRule ^script.php$ - [L]
# Move the path from the raw request into _rq
RewriteCond %{ENV:_rq} =""
RewriteCond %{THE_REQUEST} "^[^ ]+ (/path/[^/]+/[^? ]+)"
RewriteRule .* - [E=_rq:%1]
# encode the plus signs (%2B) (Loop with [N])
RewriteCond %{ENV:_rq} "/path/([^/]+)/(.*)\+(.*)$"
RewriteRule .* - [E=_rq:/path/%1/%2\%2B%3,N]
# finally, move it from the path to the query string
# ([NE] says to not re-code it)
RewriteCond %{ENV:_rq} "/path/([^/]+)/(.*)$"
RewriteRule .* /path/script.php?%1=%2 [NE]
この些細なscript.phpは、動作することを確認します。
<input readonly type="text" value="<?php echo $_GET['tag']; ?>" />
RewriteMapを使用してようやく機能するようになりました。
Httpd.confファイルRewriteMap es int:escapeにエスケープマップを追加しました
書き換えルールで使用しました
RewriteRule ([^?.]*) /abc?arg1=${es:$1}&country_sniff=true [L]