2014-02-15

【PHP/JavaScript】URLエンコードを徹底比較

Categories: PHP JavaScript
no_image.jpg

[ PR ]


久しぶりの更新です。もうお気づきかもしれませんが当ページを自鯖に移行したため時間がかかりました。

さて今回は、URLエンコードについて検証してみます。

URLエンコードとデコードの相性

URLエンコードと一重に言っても、PHPでも以下のような種類があります。

  • urlencode
  • rawurlencode
  • base64_encode

実際には、「JavaScriptでエンコードしてPHPでデコードする」といったケースも少なくないですよね。この場合はさらに以下の総当りを考えなければなくなります。

# encodeURI encodeURI-
Component
bae64.encode
(※)
urldecode ? ? ?
rawurldecode ? ? ?
base64_decode ? ? ?

(※) サードパーティのライブラリを使う場合


もうここまでくると、どの組み合わせを使えばいいのかさっぱりわかりません。(汗)

URLエンコードの都市伝説

先程の総当りですが、以下のようにするとうまくいくという都市伝説があります。

  • encodeURIurldecode
  • encodeURIComponentrawurldecode
  • base64_encodeBase64.decode(サードパーティ)

確かに意味合い的にはうまくいきそうですが、本当に上手くいくかはわかりません。

ということで、実際はどうなのか調べてみることにしました。

検証方法

できるだけ多くのケースを自動的に判断できるように、以下の方法を取りました。

  • (1) PHPでエンコードしたものをJavaScriptでデコードする
  • (2) PHPとJavaScriptでそれぞれ同じものをエンコードして、結果を比較する
  • (3) PHPとJavaScriptでそれぞれ同じものを1万回エンコードして、速度を比較する

この3つの方法に使ったソースコードを以下に貼っておきます。

実行結果

実際のPHPをここで走らせてみたかったのですが、サーバ負荷が大きいので結果として出力されるHTMLだけを貼っておきます。

(1) PHPでエンコードしたものをJavaScriptでデコードする

考察

この結果を見ると、urlencode と decodeURI は上手くいかない ということがわかります。

意外にも urlencodeの結果をdecodeURIComponentできちんとデコードできているようです。

  • urlencodedecodeURI NG
  • rawurlencodedecodeURIComponent OK
  • Base64.encodebase64_decode OK

ただ必ずしも逆はこうなるとは限らないので、気になる方は手動で検証してください。

(2) PHPとJavaScriptでそれぞれ同じものをエンコードして、結果を比較する

考察

最後の方の結果を見ると、JavaScriptのencodeURIは「/:&+=:;/?,#$」をエスケープしていないということがわかります。

また、encodeURIComponentの方も「~!*()_-」をエスケープしていないようですね。

ブラウザによって異なる可能性はありますが、

  • encodeURI
  • encodeURIComponent

をGETとPOSTに使うのは、若干不安がありますね。

ただ、encodeURIComponent はある程度エスケープを強化しているので、ある特定の文字列以外では上手くいくと思います。(そうじゃないと困ります 笑)

(3) PHPとJavaScriptでそれぞれ同じものを1万回エンコードして、速度を比較する

考察

この結果を見るとencodeURIが重いですが、何回も行うと結果がバラバラで、18ms〜60ms と変動しました。

PHPの方はサーバ性能に比例するようで、Hetemlで一度実行したときは、すべて 7ms〜9ms でした。

結論

一番良好な結果だったエンコード方式はBase64

以上の結果を見ると、全ての場合に有効なのが Base64 でした。

ただしJavaScript側で標準でサポートされていないため、ライブラリを使わないといけない欠点があります。

encodeURIComponent & rawurldecode でほとんどの場合がOK

ライブラリ不要で動くものとしては、概ね encodeURIComponentrawurldecode が有効だということがわかりました。

ただしこの場合も、特定の記号には気をつけたほうが良さそうです。

encodeURI は目的によっては使わないほうがいい

一番結果がよくなかったのが、encodeURIですね。POSTやGETに使うとエラーが起こる可能性があるので気をつけてください。

まとめ

意外と安易に使いがちなエンコードですが、今回紹介した他にも

  • escape
  • mysqli_real_escape_string
  • mysqli_escape_string

など種類が多いですよね。

用途に応じてそれぞれ異なったエンコードが行われるので、なんとなく使うのではなくて、気をつけて使いたいですね。

いきなりはじめるPHP~ワクワク・ドキドキの入門教室~
谷藤賢一
リックテレコム
売り上げランキング: 1,175

コメントはTwitterアカウントにお願いします。

RECENT POSTS


[ PR ]

.