400 Bad

この投稿は2年半前の記事です。 情報が古くなっている可能性があるので、その点ご了承ください。
2014 年 5 月 9 日 1,054日前)
2,440文字 (読了時間6分)

SPONSORED LINK

昨日ブログを書いたのですが、その登場人物S氏から「俺の携帯だとブログ見られない」という連絡を頂きました。どうも400 Bad Requestが出ていたようです。

状況をまとめると……

  • 去年までは見られていた
  • 端末は DocomoのMEDIAS ES N-05D
  • OSはAndroidの2.3系(バージョンアップはしていない様子)
  • FacebookやTwitterでソーシャルデバッギングをしかけたところ、他のAndroid2.3のユーザーは見られているとのこと

 

というわけで調べてみました。S氏には「とりあえずドコモショップに言ってOSとファームウェアをアップデートしてもらって」と伝えたのですが、ドコモ店員に向かって「このサイトが見られない」というクレームを入れたようで、なんか僕のところに電話かかってきました……。

家族を人質にでも取られない限り、ドコモショップの店員はやるまいと思いましたね。

400 Bad Requestとは

直訳すると「悪い要求」なのでクライアント(見る側)の問題ではあるようです。ググると「クッキー消せ」という情報が出てきますね。

まあ、「クッキー消して」と頼んでなんとかなる規模ならばいいのですが、沢山のユーザーを抱えるサイトで同じことが起きたらやだなと思ったので、ちょっと調べてみました。

で、色々ググったところ、 Dealing with Nginx 400 Bad Request HTTP errors というブログ記事を発見。ここによると、400 Bad requestはCookieが大き過ぎるとなるよと書いてありました。

で、最後にはNginxのドキュメントに行き当たりました。large_client_header_buffersの項目にこんなことが書いてあります。

このディレクティブはクライアントからのリクエストに含まれる大きなヘッダーを読みとるためのバッファーの数およびサイズを割り当てます。

リクエストの行は1つのバッファーのサイズより小さくないといけません。もしクライアントがそれよりも大きいヘッダーを送信した場合、nginxは ”Request URI too large(414)” を返します。

また、ヘッダーの一番長い行も1つのバッファーのサイズを超えてはいけません。超えた場合、クライアントは ”Bad request(400)”を受け取ります。

バッファーは必要に応じて分割されます。

初期値では1つのバッファーのサイズは8192バイトです。古いnginxではこの値は1ページあたりの容量と同じで、プラットフォームによって4kまたは8kとなり、動作中のリクエスト接続がkeep-aliveに移行するとバッファーは解放されます。

HttpCoreModule – Nginx Community

最後の文はちょっと翻訳怪しいですが、要するにここに設定された値を超えたヘッダーを受け取るとエラーになるよということですね。

CookieはHTTP Request Headerであり、RFCによれば(参考: Internet Explorer の cookie の数とサイズの制限)1行が4kb程度なはずなのですが、ブラウザによってはこれを超えるクッキーを許容するようです。

となると、少なくともCookieを含められる値を large_client_header_buffers に設定すれば動くんじゃないかということになりますね。したがって、これを次のように設定します。

http{
    # httpディレクティブに書きます
    large_client_header_buffers 4 256k;
}

S氏に確認しながらやった結果、最終的に256kまで増加しないと見られるようになりませんでした。そんなにCookieに保存することあるの……

結局のところ、なにによってCookieが増加しているのかはわからなかったのですが、Androidで400 Bad Requestが出ることは多いみたいですね。Google Adsenseとか、Google Analyticsとか、そういうのが原因かもしれません。

ちなみに、デバッグ中にS氏はドコモショップに行ってOSを4.xに上げてもらったようですが、それでは解決しませんでした。

今回のことから得た教訓は……

  • 端末によって起きたり起きなかったりすると、デバッグ大変。
  • Androidはマジで辛い

おまけ: client_body_buffer_sizeも設定した

今回の件でログをあさったところ、大量のエラーが出ていました。

an upstream response is buffered to a temporary file /var/cache/nginx/fastcgi_temp/1/02/0000000021 while reading upstream

PHP-FPMと通信するときにバッファに乗り切らないとファイルI/Oが発生するたみたいです。よって、client_body_buffer_sizeを大きめに設定。どうも、ページサイズの倍ぐらいないとダメっぽかったので、次のようにしました。

http{
    client_body_buffer_size 512k;
}

ここら辺はわりと適当なので、参考リンクなども熟読してください。終わり。

マスタリングNginx

マスタリングNginx [書籍]

著者Dimitri Aivaliotis

クリエーター高橋 基信

出版社オライリージャパン

出版日2013 年 10 月 26 日

商品カテゴリー大型本

ページ数244

ISBN4873116457

今これ読んでる。

Supported by amazon Product Advertising API

 

フォローしてください

ここで会ったのもなにかの縁。
高橋文樹.comの最新情報を見逃さないためにもフォローをお願いします。
めったに送らないメルマガもあります。

SPONSORED LINK

この記事について

この記事はが2014 年 5 月 9 日にプログラミングの記事として公開しました。

高橋先生の電子書籍

高橋先生の電子書籍

Amazonで電子書籍も買えます。

好きな言葉

既存の社会制度の中で生き、それを享受してきた人間にとって、そのシステムに期待するものが何もなかった者たちが、格別恐れもせずにその破壊を試みる可能性を想像することはおそらく不可能なのだ。

— ミシェル・ウエルベック

高橋先生の処女作

『途中下車』高橋文樹

2001年幻冬舎NET学生文学大賞受賞作です。

Web制作やります

Web制作やります

Web制作のご依頼は株式会社破滅派へ

不定期メルマガ

高橋文樹.comでは、不定期でニュースレターを配信しています。滅多に送らないので是非購読してください。

高橋文樹.comではプライバシーポリシーに準じて登録情報を取り扱います。