web-dev-qa-db-ja.com

スペースをプラス(+)または%20にエンコードする場合

時々、スペースはURLを+サインにエンコードします、他の時には%20にエンコードします。違いは何ですか、なぜこれが起こるのでしょうか。

424
Muhammad Hewedy

+は、URLのクエリ部分など、application/x-www-form-urlencodedコンテンツ内のスペースonlyを意味します。

http://www.example.com/path/foo+bar/path?query+name=query+value

このURLでは、パラメータ名はスペース付きのquery name、値はスペース付きのquery valueですが、パス内のフォルダ名は文字通りfoo+barnotfoo barです。

%20は、これらのコンテキストのどちらでもスペースをエンコードするための有効な方法です。そのため、URLの一部に含めるために文字列をURLエンコードする必要がある場合は、スペースを%20で置き換え、%2Bで置き換えても安全です。これは何ですか。 encodeURIComponent()はJavaScriptで行います。残念ながら、それはPHPで urlencode がすることではありません( rawurlencode は安全です)。

HTML 4.01仕様書アプリケーション/ x-www-form-urlencoded

429
bobince

http://www.example.com/some/path/to/resource?param1=value1

クエスチョンマークの前の部分は%エンコーディングを使用する必要があるため(スペースは%20)、クエスチョンマークの後はスペースに%20または+を使用できます。疑問符の後に実際の+が必要な場合は、%2Bを使用してください。

46
cerberos

だから、ここでの答えはすべて少し不完全です。 URLのスペースをエンコードするための '%20'の使用は、URIの構築方法を定義する RFC3986 で明示的に定義されています。この仕様では、スペースのエンコードに '+'を使用することについては言及されていません。この仕様だけを使用する場合、スペースは '%20'としてエンコードする必要があります。

スペースをエンコードするために '+'を使用することについての言及は、HTML仕様のさまざまな具体化から - 具体的にはコンテンツタイプ 'application/x-www-form-urlencoded'を説明しているセクションから来ます。これはフォームデータの転記に使用されます。

現在、HTML 2.0仕様 (RFC1866) はセクション8.2.2で、GETリクエストのURL文字列のQuery部分は次のようにエンコードされるべきであると明確に言っています'application/x-www-form-urlencoded'。これは、理論的には、( '?'の後の)クエリ文字列内のURLに '+'を使用することが正当であることを示唆しています。

しかし……それは本当にですか? HTMLはそれ自体がコンテンツ仕様であり、クエリ文字列を含むURLはHTML以外のコンテンツでも使用できます。さらに、最近のバージョンのHTML仕様では、 'application/x-www-form-urlencode'のコンテンツでは '+'を正当なものとして定義し続けていますが、GETリクエストクエリ文字列はそのタイプとして定義されています。実際、HTML 2.0仕様の後には、クエリ文字列のエンコードについて何も言及されていません。

どちらが質問を残します - それは有効ですか?確かに、クエリ文字列で '+'をサポートする多くのレガシーコードと、それを生成する多くのコードがあります。だからオッズは良いです、あなたが '+'を使っても壊れないでしょう。 (そして実際に、スペースとしてGETクエリで '%20'を受け入れられない主要なサイトを発見したので、私は最近これに関するすべての研究をしました。彼らは実際にはパーセントエンコードされた文字のデコードに失敗しました。使用することも関連があるかもしれません。)

しかし、HTML 2.0仕様から新しいバージョンに持ち越された言語を除いて、仕様を純粋に読むことから、URLはRFC3986によって完全にカバーされます、それはスペースが '%20'に変換されるべきであることを意味します。また、HTML文書以外のものを要求している場合は、必ずそうなるはずです。

26
zgwortz

"+"ではなく、常に%20としてスペースをエンコードすることをお勧めします。

RFC-1866(HTML 2.0仕様)で、 "application/x-www-form-urlencoded"コンテンツタイプのキーと値のペアで空白文字を "+"としてエンコードするように指定されています。 (8.2.1項サブパラグラフ1を参照)。フォームデータをエンコードするこの方法は後のHTML仕様でも与えられています、application/x-www-form-urlencodedに関する関連段落を探してください。

これは、RFC-1866がスペースをプラスとしてエンコードすることを許可するURLのそのような文字列の例です: "http://example.com/over/there?name=foo+bar"。そのため、 "?"の後にだけ、RFC-1866によれば、スペースをプラスに置き換えることができます。それ以外の場合は、スペースを%20にエンコードする必要があります。しかし、コンテキストを判断するのは難しいので、スペースを「+」としてエンコードしないことがベストプラクティスです。

RFC-3986、p.2.3で定義されている「予約されていない」以外のすべての文字をパーセントエンコードすることをお勧めします。

unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
7
Maxim Masiutin

違いは何ですか:他の答えを見てください。

+の代わりに%20を使うときは?何らかの理由でURLクエリ文字列(+)またはハッシュフラグメント(?.....)を読みやすくする場合は、#....を使用します。例:あなたは実際にこれを読むことができます:

https://www.google.se/#q=google+doesn%27t+encode+:+and+uses+%2B+instead+of+space%2B = +)

しかし、以下は読むのがずっと難しいです。(少なくとも私には)

https://www.google.se/#q=google%20doesn%27t%20oops%20:%20%20this%20text%20%2B%20is%20different%20spaces

Googleは+を使用しているので(上の最初のリンクを参照)、+が問題を解決する可能性は低いと思いますが、おそらくこれについて考えています。私は、+を自分で使うつもりです。

2
KajMagnus