[tech]HTTP GETメソッドのURIの長さ制限を調べてみた

Webの開発者をやっていると良くいわれていることですが、HTTP GETメソッドを使うなという話を聞きます。セキュリティの点もありますが、HTTP GETメソッドですべてのパラメータをサーバに送れないからというのがその理由のようです。
実際どこからでているのか、現在もそうなのか?という疑問を感じたので、HTTP GETの制限を調べてみました。

RFCではどうなっているの?

まずHTTP1.1のRFC2616を調べました。
とりあえず、日本語訳がありましたので、引用いたします。http://www.studyinghttp.net/cgi-bin/rfc.cgi?2616より

HTTP プロトコルでは、URI の長さにどんな制限も設けていない。 サーバは、自身が持つどんなリソースのURI も扱えなければならないし、もしそのような URI を生成する GET ベースのフォームを用意するなら、無制限の長さの URI を扱えるべきである。 もし、その URI がサーバが処理できるものよりも長ければ、サーバは 414 (Request-URI Too Long) ステータスを返すべきである (section 10.4.15 参照)。


注: いくつかの古いクライアントやプロクシ実装は 255 バイトを超える長さを持つ URI を適切にサポートしていないかもしれないので、サーバはそのような URI に頼る場合は注意を払うべきである。

つまりHTTP GETメソッドにはRFC上、URIに255byteの制限はないのですね。良くいわれているような255byte以上送信できないというのは、ここから来ている誤解ですね。
現実問題、古いクライアントやプロクシの実装を気にする必要がないでしょうから、255バイトというのは気にする必要がないでしょう。

各Webサーバはどうなっているの?

RFC上は、HTTP GETのURIの長さに上限がないことがわかりました。では、Webサーバでは、どこまで扱えるのでしょうか?

apache2.2

apache2.2ではデフォルトは、8190バイトがデフォルトです。しかし、LimitRequestLineを設定することで、変更可能です。http://httpd.apache.org/docs/2.2/mod/core.html#limitrequestlineより引用すると、

このディレクティブは、HTTP リクエスト行内で許容されるバイト数 bytes を指定します。

LimitRequestLine ディレクティブにより、 クライアントからの HTTP リクエスト行の許容サイズを増減できます。 リクエスト行は、HTTPメソッド、URIプロトコルバージョンから成っており、LimitRequestLine はサーバへのリクエストに対して 許容するリクエスURI の長さを制限することになります。 サーバは、GET リクエストのクエリ部分も含めて、リソースの名前が入るに足る大きさを必要とします。

ということで、URIの上限をさらに大きくすることも可能です。

IIS4.0, 5.0

IISはURL Scanをインストールしているかどうかで設定が変わります。レジストリを設定することで、URLの長さを指定することができるようになっています。
http://technet.microsoft.com/ja-jp/library/bb878118.aspxによるとURL Scanをインストールしている場合は、MaxQueryString 2048文字、MaxUrl260文字が上限です。URL Scanをインストールしていない場合は、MaxClientRequestBufferによりIISへのリクエストの総バイト数が指定でき

IIS 4.0 2MB
IIS 5.0 128k
IIS 5.0 Windows 2000 Server SP4 16k

となります。

ブラウザはどうなっているの?

いくらサーバで受け付けられたとしても、ブラウザからリクエストを送信できなければ意味がありません。それではブラウザには制限がないのでしょうか?

IE

IEMicrosoftがURLの上限に関する情報を公開しています。http://support.microsoft.com/?id=208427によると、

Internet Explorer では、URL (Uniform Resource Locator) に使用できる最大文字数は 2,083 文字です。

GET メソッドを使用する場合、最大文字数は 2,083 文字に制限されます (実際のパスも含めた文字数)。

IE3.0〜IE8.0までが対象となっていますので、ほぼすべてのバージョンで2083文字以上の指定ができないと考えた方が良いですね。

Safari

仕様やドキュメントらしいものが見当たらなかったので、TextAreaにデータを入れて、送信して動作を確認しました。
Safari v4.0.3 Mac OSX 10.6.1でテストさせてみましたが、1Mbyteまでは送信可能でした。おそらく制限はないと思われます。

Firefox

仕様らしいものが見当たらなかったので、TextAreaにデータを入れて、送信して動作を確認しました。
Firefox v3.0.11 Mac OSX 10.6.1でテストさせてみましたが、1Mbyteまでは送信可能でした。おそらく制限はないと思われます。
Firefox v3.5.3 でもテストしたのですが、TextAreaにデータを貼付ける方法では1Mbyte程度でブラウザが固まってしまいました。

フレームワーク

Google App Engine(Python)

みんな大好きなGoogle App Engineですが、制限は2047バイトです。dev_appserver.pyのMAX_URL_LENGTHを参照してみてください。

未調査

まとめ

まとめます。

HTTP1.1の仕様上はHTTP GETで転送できるデータ量(=URIの長さ)には上限がありません。Webサーバでデフォルトは制限されていますが、設定で変更することが可能です。しかし、IEにはURI長が2083文字という制限があるため、実質的な上限は2083文字となります。

制限が小さいせいで、IEデファクトスタンダードになっているのですね。勉強になりました。
間違いなどありましたら、コメントにてご連絡をお願いします。