HTTPサーバーとWeb開発

52. 文字「#」は使用してはならない理由。

URLに文字「#」が複数含まれているとIE(InternetExproler)は、2番目の「#」以降の後続する文字列を
HTTPサーバーに送ってくれない。
これはIEの障害ではなく、http:スキーム(構文)での決まりごとに従っているためである。

URI (Uniform Resource Identifier の略、URLを含めた接続リソースを特定するための手段
全体を指す)では、ASCII以外の文字はそのままでは使えないことはご存知の方も多いと思う。
(ブランクであれば「%20」にエンコードする必要がある)
ところがASCIIでも除外されている文字がいくつか存在し、それらも同様にエンコードする必要が
あるのだ。(RFC2396規定の「使用除外文字」という)
「#」も実はそのひとつなのである。

通常「#」はアンカーとして使用される。(「#」をそのままエンコードせずに使用すると、ブラウザに
アンカーとして解釈される)
アンカーとはリンクの記述が <a href="index.html#TOPIC"> あるいは <a href="#news">
なっているものを指す。
前者であれば index.html の中の #TOPIC として規定された箇所へ、後者であれば現在表示
されているページの #news として規定された箇所にジャンプするわけである。

つまりURL(URI)に文字「#」がエンコードされていない状態で複数含まれている場合、
最初の「#」はアンカーとして解釈され、2番目以降の「#」は使用除外文字であるために以降の文字列
が全てカットされたり、2番目以降の「#」が脱落するなど、予想外の挙動につながってしまう。

<input type="hidden" name="#NAME1" value="VALUE1">
<input type="hidden" name="#NAME2" value="VALUE2">
<input type="hidden" name="#NAME3" value="VALUE3">
                       :

といったフォーム内の要素を送信する場合は、ほんの少しではあるが注意していただきたい。

一般的な手法である <input type="submit" value="送信"> という送信ボタンをクリック
させてSubmit(送信)するならば特に問題は無い。GET送信であれば

「http://IP-ADDRESS:PORT/cgi-bin/MYCGI?%23NAME1=VALUE1&%23NAME2=VALUE2&%23NAME3=VALUE3&・・・」

という具合に「#」はブラウザによって「%23」に自動でエンコードされて送信されるからである。
サーバ側では「%23」を元通り「#」として処理してくれる。

ところがJavaScript等で、単純にそれぞれの項目名と値を結合させて送信を行う場合は
送信文字列が

「http://IP-ADDRESS:PORT/cgi-bin/MYCGI?#NAME1=VALUE1&#NAME2=VALUE2&#NAME3=VALUE3&・・・」

のようになる。
このときは前述の通り、最初の「#」はアンカーとして解釈され、以降の「#」は使用除外文字で
あるために以下の文字列の全てあるいは一部が脱落した状態となる。
そのためブラウザからは

「http://IP-ADDRESS:PORT/cgi-bin/MYCGI?#NAME1=VALUE1&」
「http://IP-ADDRESS:PORT/cgi-bin/MYCGI?#NAME1=VALUE1&NAME2=VALUE2&NAME3=VALUE3&・・・」

といった文字列が送信されるが、いずれもパラメータが十分でないため結果的にPGMではエラー
を出してしまう。

何の不安も無くWebAppを運用するためには、やはり文字「#」はできるだけ使用しないように
こころがけたい。