Webサーバに送信されるクエリ文字列をエンコードするとき - いつescape()
を使うのか、そしていつencodeURI()
またはencodeURIComponent()
を使うのか:
エスケープを使う:
escape("% +&=");
OR
encodeURI()/ encodeURIComponent()を使用してください。
encodeURI("http://www.google.com?var1=value1&var2=value2");
encodeURIComponent("var1=value1&var2=value2");
使用しないでください。 escape()
は付録 で定義されています。B.2.1.2エスケープ および のAnnex 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
が続くことは許可されません。
実用的なURLが欲しいときにencodeURIを使用してください。この電話をかける:
encodeURI("http://www.example.org/a file with spaces.html")
取得するため:
http://www.example.org/a%20file%20with%20spaces.html
URLを破壊して戻るので、encodeURIComponentを呼び出さないでください。
http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html
URLパラメータの値をエンコードする場合は、encodeURIComponentを使用してください。
var p1 = encodeURIComponent("http://example.org/?a=12&b=55")
それからあなたはあなたが必要とするURLを作成することができます:
var url = "http://example.net/?param1=" + p1 + "¶m2=99";
そして、あなたはこの完全なURLを手に入れるでしょう:
http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55¶m2=99
EncodeURIComponentは'
文字をエスケープしないことに注意してください。よくあるバグはそれを使ってhref='MyUrl'
のようなhtml属性を作成することです。これはインジェクションのバグを被る可能性があります。文字列からhtmlを作成する場合は、属性の引用符に"
の代わりに'
を使用するか、または追加のエンコード層を追加します('
は%27としてエンコードできます)。
このタイプのエンコーディングの詳細については、次のものを確認できます。 http://en.wikipedia.org/wiki/Percent-encoding
encodeURI()
とencodeURIComponent()
の違いは、encodeUICではなくencodeURIComponentによってエンコードされた11文字です。
このコードを使って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);
私はこの記事が啓発を見つけた: Javascriptの狂気:クエリ文字列の解析
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!
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
ご覧のとおり、一重引用符はエンコードされていません。問題を解決するために、私は自分のプロジェクトの問題を解決するために2つの関数を作成しました。URLのエンコード:
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 "";
}
encodeURI() - escape()関数はHTTPではなくJavaScriptエスケープ用です。
小さな比較表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
これらの方法をそのまま使用しないことをお勧めします。正しいことをするあなた自身の関数を書いてください。
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
また、それらはすべて異なる文字セットをエンコードしているので、必要なものを適切に選択してください。 encodeURI()は、encodeURIComponent()よりも少ない文字数をエンコードします。これは、escape()よりも少ない文字数(dannypの観点とは異なります)をエンコードします。
Javascriptをエンコードする目的で3つの作り付けの関数を与えました -
escape() - @*/+
をエンコードしませんこのメソッドはECMA 3以降は推奨されていないので、避けるべきです。
encodeURI() - ~!@#$&*()=:/,;?+'
をエンコードしませんURIは完全なURIであると想定しているため、URIで特別な意味を持つ予約文字はエンコードしません。このメソッドは、URLの特別なセグメントではなく、完全なURLを変換することを目的としている場合に使用されます。例 - encodeURI('http://stackoverflow.com');
は - http://stackoverflow.comを与えます
encodeURIComponent() - - _ . ! ~ * ' ( )
をエンコードしないこの関数は、特定の文字の各インスタンスを、文字のUTF-8エンコードを表す1、2、3、または4つのエスケープシーケンスで置き換えることによって、URI(Uniform Resource Identifier)コンポーネントをエンコードします。このメソッドはURLのコンポーネントを変換するために使われるべきです。例えば、いくつかのユーザ入力を追加する必要があります。例 - encodeURI('http://stackoverflow.com');
は与える - http%3A%2F%2Fstackoverflow.com
このエンコーディングはすべてUTF 8で実行されます。つまり、文字はUTF-8形式に変換されます。
encodeURIComponentは、エンコードされた文字とencodeURIのシャープ記号をエンコードするという点でencodeURIと異なります
さまざまな方法を試してみることは、さまざまな用途や機能が何であるかをよく理解した後でも、健全性を確認するのに適していることがわかりました。
その目的のために私は このウェブサイト が私が何かを適切にしているという私の疑いを確認するために非常に有用であることを見つけました。それは、解釈するのがかなり難しい場合があるencodeURIComponentの文字列をデコードするのにも有用であることが証明されています。持っているのに最適なブックマーク:
Johannのテーブル に触発されて、私はテーブルを拡張することにしました。どの[ASCII文字がエンコードされるのかを見たかったのです。
var ascii = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var encoded = [];
ascii.split("").forEach(function (char) {
var obj = { char };
if (char != encodeURI(char))
obj.encodeURI = encodeURI(char);
if (char != encodeURIComponent(char))
obj.encodeURIComponent = encodeURIComponent(char);
if (obj.encodeURI || obj.encodeURIComponent)
encoded.Push(obj);
});
console.table(encoded);
表はエンコードされた文字のみを示しています。空のセルは、元の文字とエンコードされた文字が同じであることを意味します。
念のため、 urlencode()
vs rawurlencode()
唯一の違いはスペース文字のエンコーディングです。
<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>
私はこの機能を持っています...
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;
};
受け入れられた答えは良いです。最後の部分を拡張するには
EncodeURIComponentは '文字をエスケープしないことに注意してください。よくあるバグはこれを使ってhref = 'MyUrl'のようなHTML属性を作成することです。文字列からhtmlを作成している場合は、属性の引用符に "の代わりに"を使用するか、またはエンコーディングのレイヤを追加します( '%27としてエンコードできます)。
あなたが安全側になりたいのであれば、 パーセントエンコーディング予約されていない文字 もエンコードする必要があります。
あなたはそれらをエスケープするためにこのメソッドを使うことができます(source Mozilla )
function fixedEncodeURIComponent(str) {
return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
return '%' + c.charCodeAt(0).toString(16);
});
}
// fixedEncodeURIComponent("'") --> "%27"
@ 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.log
をconsole.table
に置き換えます。