web-dev-qa-db-ja.com

HTTPクエリ文字列ではどの文字をエスケープする必要がありますか?

この質問は、?マーク文字の後に表示されるURLのクエリ文字列部分の文字に関するものです。

Wikipedia ごとに、特定の文字はそのまま残され、他の文字はエンコードされます(通常は%エスケープシーケンスで)。

私はこれを実際の仕様まで追跡しようとしてきたので、Wikipediaページのすべての箇条書きの背後にある正当性を理解しています。

矛盾例1:

HTML仕様 は、スペースを+としてエンコードし、残りを RFC1738 に委ねます。ただし、このRFCでは、~は安全ではなく、さらに「[a] ll安全でない文字は常にURL内でエンコードする必要がある」としています。これはウィキペディアと矛盾しているようです。

実際には、IE8は生成するクエリ文字列で~をエンコードしますが、FF3はそのままにします。

矛盾例2:

ウィキペディアでは、言及していないすべての文字をエンコードする必要があると述べています。 !はウィキペディアに記載されていません。しかし、 RFC1738 は、!が「特殊な」文字であり、「エンコードされていない状態で使用できる」と述べています。これは、エンコードする必要があるというウィキペディアと矛盾しているようです。

実際には、IE8は生成するクエリ文字列で!をエンコードしますが、FF3はそのままにします。

このモラルは、おそらくウィキペディアと仕様の間で疑わしい文字をエンコードすることになると理解しています。 [A-Za-z0-9]以外のすべてをエンコードすることも考えられます。これに関する実際の基準を知りたいだけです。

結論

ウィキペディアで説明されているアルゴリズムは、 RFC3986非予約文字 ではない文字を正確にエンコードします。つまり、英数字と-._~以外のすべての文字をエンコードします。特別な場合として、スペースはRFC3986に従って+ではなく%20としてエンコードされます。

一部のアプリケーションは古いRFCを使用します。比較のために、 RFC2396非予約文字 は英数字と!'()*-._~です。

比較のため、 HTML5 working draft algorithm は、英数字と*-._以外のすべての文字をエンコードします。スペースの特別な場合のエンコードは+のままです。注目すべき違いは、*がエンコードされていないことと~がエンコードされていることです。 (技術的には、*reservedにあるにもかかわらず、*queryにある場合でも、sub-delimsのこの処理はRFC3986と互換性があります。)

46
Jason Kresowaty

答えは、RFC 3986文書、具体的には セクション3.4 にあります。

クエリコンポーネントは、最初の疑問符( "?")文字で示され、シャープ記号( "#")文字またはURIの末尾で終了します。

...

文字のスラッシュ( "/")および疑問符( "?")は、クエリコンポーネント内のデータを表す場合があります。

技術的には、RFC 3976-3.4はクエリコンポーネントを次のように定義しています。

query       = *( pchar / "/" / "?" )

この構文は、クエリにpcharおよび/および?pcharは、パス文字の別の指定を指します。 RFC 3986の Appendix A は、関連するABNF定義の一覧です。

query         = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

したがって、すべての英数字およびパーセントでエンコードされた文字に加えて、クエリには次のエンコードされていない文字を合法的に含めることができます。

/ ? : @ - . _ ~ ! $ & ' ( ) * + , ; =

もちろん、「=」と「&」は通常、クエリ内で特別な意味を持つことに注意してください。

42
PJ King