encodeURI / encodeURIComponentの代わりにいつエスケープを使用することになっていますか?


1392

Webサーバーに送信するクエリ文字列をエンコードするとき-いつescape()使用するencodeURI()か、またはor を使用するかencodeURIComponent()

エスケープを使用:

escape("% +&=");

または

encodeURI()/ encodeURIComponent()を使用します

encodeURI("http://www.google.com?var1=value1&var2=value2");

encodeURIComponent("var1=value1&var2=value2");

111
これは一般的なユースケースでencodeURIComponent("var1=value1&var2=value2")ないことを指摘する価値があります。その例は=and をエンコードしますが&、これはおそらく意図したものではありません!encodeURIComponent通常、各キーと値のペア(各の後の部分=)の値のみに個別に適用されます。
ティモシーシールズ

3
あなたは鍵に何かをする必要がありますか?中に=がある場合はどうなりますか?(それは可能ですか?)
Mala

3
@Mala私はまだ一般的なWebプログラミングの初心者ですが、限られた経験で使用したのは、キーと値を別々にエンコードして、「=」が維持されるvar params = encodeURIComponent(key) + '=' + encodeURIComponent(value);ようにすることです。
ネッドシェアーズ2014年

1
@nedshares私はそれで遊んでいましたが、私の知る限り、キーはエンコードされていないようです...少なくとも同じ方法ではありません。たぶん、キーに=があるのは仕様に反していますか?
マラ2014

1
また、最近のJavaScriptの実装では、URLとそのクエリ文字列を操作するための高レベルのインターフェースURLURLSearchParamsが提供されていることにも注意してください。
Bart Robinson

回答:


1914

逃れる()

使わないで! escape()セクションB.2.1.2エスケープで定義されており、附属書Bの紹介文は次のように述べています

...この付録で指定されているすべての言語機能と動作には、1つ以上の望ましくない特徴があり、レガシー使用法がない場合、この仕様から削除されます。...
...プログラマは、新しいECMAScriptコードを作成するときに、これらの機能や動作を使用したり想定したりしないでください。

動作:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape

特殊文字は@ * _ +-。/を除いてエンコードされます

コード単位の値が0xFF以下の文字の16進形式は、2桁のエスケープシーケンスです%xx

より大きなコード単位の文字の場合、4桁のフォーマット%uxxxxが使用されます。これは、(RFC3986で定義されている)クエリ文字列内では許可されていません。

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

パーセント記号は、直後に2桁の16進数が続く場合にのみ使用できます。パーセント記号の後にuは使用できません。

encodeURI()

機能するURLが必要な場合は、encodeURIを使用してください。この電話をかける:

encodeURI("http://www.example.org/a file with spaces.html")

取得するため:

http://www.example.org/a%20file%20with%20spaces.html

encodeURIComponentを呼び出さないでください。URLが破壊されて返されます。

http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html

encodeURIComponent()

URLパラメータの値をエンコードする場合は、encodeURIComponentを使用します。

var p1 = encodeURIComponent("http://example.org/?a=12&b=55")

次に、必要なURLを作成します。

var url = "http://example.net/?param1=" + p1 + "&param2=99";

そして、あなたはこの完全なURLを取得します:

http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55&param2=99

encodeURIComponentは'文字をエスケープしないことに注意してください。一般的なバグは、それを使用してのようなhtml属性を作成することhref='MyUrl'です。これにより、インジェクションバグが発生する可能性があります。文字列からhtmlを構築する場合"'、属性の引用符の代わりにを使用するか、エンコーディングのレイヤーを追加します('%27としてエンコードできます)。

このタイプのエンコーディングの詳細については、http//en.wikipedia.org/wiki/Percent-encodingを確認してください


31
@Francoisは、受信サーバーによっては、エスケープが次のような上位ASCIIまたは非ASCII文字をエンコードする方法を正しくデコードできない場合があります。たとえば、エスケープでエンコードした場合、PythonのFieldStorageクラスは上記の文字列を正しくデコードしません。
レイ

22
@Francois escape()は、文字、数字、および*@-_+./を除く下位128 ASCII文字をエンコードしますが、unescape()はescape()の逆です。私の知る限り、これらはURLのエンコード用に設計されたレガシー関数であり、下位互換性のためにのみ実装されています。一般に、それらのために設計されたアプリ/ Webサービスなどとやり取りしない限り、使用しないでください。
アンソニーディサンティ

3
もちろん、URLをURIコンポーネントとして渡そうとしているのでなければ、encodeURIComponentを呼び出してください。
トム

4
なぜ単一引用符を処理しないのですか?
Eric

11
@Eric単一引用符はURI内で発生する完全に有効な文字であるため、単一引用符はエンコードしません(RFC-3986)。この問題は、単一引用符が有効な文字ではない HTML内にURIを埋め込むと発生します。その結果、URIもHTML文書に配置される前に'、「HTMLエンコード」される必要があります(これはに置き換えられます')。
リー

441

との違いはencodeURI()encodeURIComponent()encodeURIComponentではなく、encodeURIComponentでエンコードされた正確に11文字です。

encodeURIとencodeURIComponentの10の違いがある表

次のコードを使用して、Google Chromeのconsole.tableでこのテーブルを簡単に生成しました。

var arr = [];
for(var i=0;i<256;i++) {
  var char=String.fromCharCode(i);
  if(encodeURI(char)!==encodeURIComponent(char)) {
    arr.push({
      character:char,
      encodeURI:encodeURI(char),
      encodeURIComponent:encodeURIComponent(char)
    });
  }
}
console.table(arr);


このブラウザに依存していませんか?
Pacerier 2014

4
@bladnman encodeURIおよびencodeURIComponentは、すべての主要なブラウザーでこのように機能するはずです。上記のコードは、どちらもconsole.tableをサポートしているため、ChromeとFirefoxでテストできます。(Firefoxとクロームを含む)他のブラウザで次のコードを使用することができますvar arr=[]; for(var i=0;i<256;i++){var char=String.fromCharCode(i); if(encodeURI(char)!==encodeURIComponent(char)) console.log("character: "+char + " | encodeURI: " +encodeURI(char) + " |encodeURIComponent: " + encodeURIComponent(char) ) }
ヨハンEchavarria

1
私は@Pacerier :)を意味しました
Johann Echavarria '27 / 09/27

@Pacerierは、元の仕様があいまいでない限り、さまざまなブラウザーで同一でなければなりません...また、stackoverflow.com
Christophe Roussy

2
私はこの数回を投票する必要があります!残念ながら、賛成投票は1回しかできません。
ラマザンポラット

46

私はこの記事を啓発的に見つけました: Javascript Madness:Query String Parsing

decodeURIComponentが '+'を正しくデコードしなかった理由を理解しようとしたときに、これを見つけました。これが抜粋です:

String:                         "A + B"
Expected Query String Encoding: "A+%2B+B"
escape("A + B") =               "A%20+%20B"     Wrong!
encodeURI("A + B") =            "A%20+%20B"     Wrong!
encodeURIComponent("A + B") =   "A%20%2B%20B"   Acceptable, but strange

Encoded String:                 "A+%2B+B"
Expected Decoding:              "A + B"
unescape("A+%2B+B") =           "A+++B"       Wrong!
decodeURI("A+%2B+B") =          "A+++B"       Wrong!
decodeURIComponent("A+%2B+B") = "A+++B"       Wrong!

11
あなたがリンクしている記事は、多くのナンセンスを含んでいます。私には、作者自身が関数が適切に使用される目的を理解していなかったようです...
Christoph

2
@Christophそれは私にはすべて合理的に見えます。特に、encodeURIかなりあいまいなエッジケースでのみ有用であり、実際に存在する必要はないようだと私は彼に同意します。私は彼といくつかの意見の違いがありますが、そこにはまったく偽りや馬鹿げたことは何もありません。何がナンセンスだと思いますか?
Mark Amery 2013

1
要素のenctype属性はFORM、サーバーに送信するフォームデータセットをエンコードするために使用されるコンテンツタイプを指定します。 application / x-www-form-urlencoded これはデフォルトのコンテンツタイプです。このコンテンツタイプで送信されるフォームは、次のようにエンコードする必要があります:[...] スペース文字は「+」に置き換えられ、[...]英数字以外の文字は「%HH」に置き換えられます[...] 参考:HTML4 SEPC
cychoi

2
encodeURIComponent( 'A + B')。replace(/ \%20 / g、 '+')+ '\ n' + decodeURIComponent( "A +%2B + B" .replace(/ \ + / g、 '%20' ));
Zlatin Zlatev 2015年

39

encodeURIComponentがをエンコードしない-_.!~*'()ため、データをxml文字列でphpに送信する際に問題が発生します。

例えば:
<xml><text x="100" y="150" value="It's a value with single quote" /> </xml>

一般的な脱出 encodeURI
%3Cxml%3E%3Ctext%20x=%22100%22%20y=%22150%22%20value=%22It's%20a%20value%20with%20single%20quote%22%20/%3E%20%3C/xml%3E

ご覧のとおり、単一引用符はエンコードされていません。問題を解決するために、URLをエンコードするために、プロジェクトの問題を解決する2つの関数を作成しました。

function encodeData(s:String):String{
    return encodeURIComponent(s).replace(/\-/g, "%2D").replace(/\_/g, "%5F").replace(/\./g, "%2E").replace(/\!/g, "%21").replace(/\~/g, "%7E").replace(/\*/g, "%2A").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29");
}

デコードURL:

function decodeData(s:String):String{
    try{
        return decodeURIComponent(s.replace(/\%2D/g, "-").replace(/\%5F/g, "_").replace(/\%2E/g, ".").replace(/\%21/g, "!").replace(/\%7E/g, "~").replace(/\%2A/g, "*").replace(/\%27/g, "'").replace(/\%28/g, "(").replace(/\%29/g, ")"));
    }catch (e:Error) {
    }
    return "";
}

5
また、#(ポンド/ハッシュ/番号)記号(%23)も実行しません。
xr280xr 14

1
@ xr280xrどういう意味ですか?encodeURIComponentは#を%23にエンコードします(おそらく2014年には行われなかったのでしょうか?)
DavidBalažicOct

38

encodeURI()-escape()関数は、HTTPではなくJavaScriptエスケープ用です。


次のようなURLがある場合:var url = "http://kuler-api.adobe.com/rss/get.cfm?startIndex=0&itemsPerPage=20&timeSpan=0&listType=rating"...そして、次のようにGoogle Ajax APIを介してアクセスしたい場合:var gurl = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + url;...次に、を使用する必要がありますescape(url)encodeURI(url)そのように見えるパラメーターでは機能しません。
ランスポラール2010

15
ecnodeURIComponent(url)を使用する必要があります
Ustaman Sangat

2
3つの機能すべてに問題があります。仕事をする独自の関数を作成することをお勧めします。
ジェリージョセフ

17

小さな比較表Java対JavaScript対PHP。

1. Java URLEncoder.encode (using UTF8 charset)
2. JavaScript encodeURIComponent
3. JavaScript escape
4. PHP urlencode
5. PHP rawurlencode

char   JAVA JavaScript --PHP---
[ ]     +    %20  %20  +    %20
[!]     %21  !    %21  %21  %21
[*]     *    *    *    %2A  %2A
[']     %27  '    %27  %27  %27 
[(]     %28  (    %28  %28  %28
[)]     %29  )    %29  %29  %29
[;]     %3B  %3B  %3B  %3B  %3B
[:]     %3A  %3A  %3A  %3A  %3A
[@]     %40  %40  @    %40  %40
[&]     %26  %26  %26  %26  %26
[=]     %3D  %3D  %3D  %3D  %3D
[+]     %2B  %2B  +    %2B  %2B
[$]     %24  %24  %24  %24  %24
[,]     %2C  %2C  %2C  %2C  %2C
[/]     %2F  %2F  /    %2F  %2F
[?]     %3F  %3F  %3F  %3F  %3F
[#]     %23  %23  %23  %23  %23
[[]     %5B  %5B  %5B  %5B  %5B
[]]     %5D  %5D  %5D  %5D  %5D
----------------------------------------
[~]     %7E  ~    %7E  %7E  ~
[-]     -    -    -    -    -
[_]     _    _    _    _    _
[%]     %25  %25  %25  %25  %25
[\]     %5C  %5C  %5C  %5C  %5C
----------------------------------------
char  -JAVA-  --JavaScript--  -----PHP------
[ä]   %C3%A4  %C3%A4  %E4     %C3%A4  %C3%A4
[ф]   %D1%84  %D1%84  %u0444  %D1%84  %D1%84

12

これらの方法をそのまま使用しないことをお勧めします。正しいことを行う独自の関数を記述します。

MDNは、次に示すURLエンコーディングの良い例を示しています。

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" + encodeRFC5987ValueChars(fileName);

console.log(header); 
// logs "Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt"


function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            //  so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent


1
すばらしい答えです(
Chrome

10

また、それらはすべて異なる文字セットをエンコードし、必要なものを適切に選択することを覚えておいてください。encodeURI()は、encodeURIComponent()よりも少ない文字数をエンコードします。encodeURIComponent()は、escape()よりも少ない(そしてdannypのポイントとは異なる)文字をエンコードします。


8

javascriptをエンコードする目的で、3つの組み込み関数が提供されています-

  1. escape()-エンコードしない@*/+ このメソッドはECMA 3以降は非推奨であるため、回避する必要があります。

  2. encodeURI()-エンコードしない~!@#$&*()=:/,;?+' URIは完全なURIであると想定しているため、URIで特別な意味を持つ予約文字はエンコードしません。このメソッドは、URLの特別なセグメントではなく、完全なURLを変換することを目的とする場合に使用されます。例- encodeURI('http://stackoverflow.com'); 与える-http://stackoverflow.com

  3. encodeURIComponent()-エンコードしない - _ . ! ~ * ' ( ) この関数は、特定の文字の各インスタンスを文字のUTF-8エンコードを表す1、2、3、または4つのエスケープシーケンスで置き換えることにより、Uniform Resource Identifier(URI)コンポーネントをエンコードします。このメソッドは、URLのコンポーネントを変換するために使用する必要があります。たとえば、いくつかのユーザー入力を追加する必要があります例- encodeURIComponent('http://stackoverflow.com'); 与える-http%3A%2F%2Fstackoverflow.com

このエンコーディングはすべてUTF 8で実行されます。つまり、文字はUTF-8形式に変換されます。

encodeURIComponentは、encodeURIとは異なり、予約された文字とエンコードURIの番号記号をエンコードします。


3

私は、さまざまな方法を実験することは、さまざまな用途と機能が何であるかをよく理解した後でも、適切な健全性チェックであることがわかりました。

そのために、私はこのウェブサイトが私が適切に何かをしているという私の疑いを確認するのに非常に役立つとわかりました。また、encodeURIComponentの文字列をデコードするのにも役立ちます。これは、解釈が難しい場合があります。持っておくと便利なブックマーク:

http://www.the-art-of-web.com/javascript/escape/


2

受け入れられた答えは良いです。最後の部分を拡張するには:

encodeURIComponentは '文字をエスケープしないことに注意してください。一般的なバグは、それを使用して、href = 'MyUrl'などのHTML属性を作成することです。これにより、インジェクションバグが発生する可能性があります。文字列からhtmlを構築する場合は、属性の引用符に 'の代わりに "を使用するか、エンコーディングのレイヤーを追加します('は%27としてエンコードできます)。

安全にしたい場合は、予約されていない文字のパーセントエンコードもエンコードする必要があります。

このメソッドを使用してそれらをエスケープすることができます(ソースMozilla

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}

// fixedEncodeURIComponent("'") --> "%27"

2

@ johann-echavarriaの答えを現代的に書き換えたもの:

console.log(
    Array(256)
        .fill()
        .map((ignore, i) => String.fromCharCode(i))
        .filter(
            (char) =>
                encodeURI(char) !== encodeURIComponent(char)
                    ? {
                          character: char,
                          encodeURI: encodeURI(char),
                          encodeURIComponent: encodeURIComponent(char)
                      }
                    : false
        )
)

あなたがテーブルを使用することができるかどうか、交換するconsole.logconsole.table(きれいに出力用)。


2

ヨハンのテーブルに触発されて、テーブルを拡張することにしました。どのASCII文字がエンコードされるかを確認したいと思いました。

console.tableのスクリーンショット

表は、エンコードされた文字のみを示しています。空のセルは、元の文字とエンコードされた文字が同じであることを意味します。


念のため、urlencode()vsの別のテーブルを追加しますrawurlencode()。唯一の違いは、スペース文字のエンコードです。

console.tableのスクリーンショット

<script>
<?php
$ascii = str_split(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 1);
$encoded = [];
foreach ($ascii as $char) {
    $obj = ["char" => $char];
    if ($char != urlencode($char))
        $obj["urlencode"] = urlencode($char);
    if ($char != rawurlencode($char))
        $obj["rawurlencode"] = rawurlencode($char);
    if (isset($obj["rawurlencode"]) || isset($obj["rawurlencode"]))
        $encoded[] = $obj;
}
echo "var encoded = " . json_encode($encoded) . ";";
?>
console.table(encoded);
</script>

1

私はこの機能を持っています...

var escapeURIparam = function(url) {
    if (encodeURIComponent) url = encodeURIComponent(url);
    else if (encodeURI) url = encodeURI(url);
    else url = escape(url);
    url = url.replace(/\+/g, '%2B'); // Force the replacement of "+"
    return url;
};

4
@ChristianVielma escape()は非推奨ですが、w3schools.comを参照することはありません。w3fools.comを参照してください
ジェリージョセフ

4
@Christian Vielma-W3Schoolsの参考資料は物議を醸しにくく、有用であると考える人もいます。W3Schoolsが参照されることは決してないことに誰もが同意するわけではありません。
DavidRR 2014年

2
W3Schoolsはひどいラップを受けています。確かにそれらは常に正確であるとは限りませんが、それでもまた、まったく間違っている多くのブログ投稿に遭遇しました。私にとっては、いくつかの用語を学ぶことは、時には素晴らしい出発点となり、他のリソースについて少し詳しく説明します。最も重要なことは、この種のものに関しては、単一のリソースが聖書的であってはならないということです。
ryandlf

@molokolocoはこの関数を、encodeURI存在しないがescape存在するバージョンへのフォールバックとして書いたようです。
SOFe 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.