ブラウザのコンソールに「net::ERR_CONNECTION_RESET」「Failed to load resource: ネットワーク接続が切れました。」と表示された場合

webシステムの開発をしていて、ブラウザから比較的大きなファイルをサーバに送信しようとしたときに正常に終了しないケースを発見しました。
具体的には、2MB程度までは複数個のファイルを指定しても問題なく正常終了するのですが、5MB、10MB、15MB…と増やしていくと処理が失敗するようになります。

ブラウザや環境によって表示されるメッセージは異なるようなのですが、開発者向けのコンソールを見ると、Chromeでは「net::ERR_CONNECTION_RESET」、Safariでは「Failed to load resource: ネットワーク接続が切れました。」と表示されます。
その他のブラウザではなにも表示されないケースもあるようです。名称未設定

この原因についてネットで検索してみると、「IPv6を切れ」や「ブラウザのキャッシュを削除しろ」などいろいろな意見がありますが、これだ!という決定打はないようです。

ネットで見つかった情報をもとに対応をしてみたのですが解決できず、いろいろと試してみたところ、私の環境では───

アンチウィルスソフトが原因

になっていることがわかりました。

ウィルス対策として導入している『ESET Cyber Security Pro』(mac用)、『ESET SMART SECURITY』(Windows用)のWebアクセス保護機能が悪さをしていました。
設定画面からこの機能をオフにすると正常に動作するようになりました。

お悩みの方は、一度アンチウィルスソフトやファイアウォールなどの設定を確認してみると良いかもしれません。


今回、フロント側のJavaScript/jQueryからサーバ側のJava/JEEにファイルを送信するという機能を実装していたのですが、問題を発見してから挙動を確かめていると「100%失敗するのではなく、ときどき正常に終了することもある」という開発者泣かせの厄介なケースであることが判明しました。

FirefoxのFirebugアドオンの『ネットワーク』タブでリクエストの状況を見ると、失敗しつつときどき成功という状態が確認できます。
というか、失敗しているときはHTTPステータスコードも返ってきていないっぽい。

スクリーンショット 2017-05-10 19.07.15

とりあえず、手間がかからなく問題を捕まえやすそうなJavaScriptのデバッガを使って処理を呼び出しているところにブレイクポイントをしかけてみます。
空値が返ってきてヒントになりそうな情報がつかめません。ブラウザによってはあらぬところに処理が飛んでいきます。

次に、JEEサーバにデプロイしているwebアプリケーションの適当な場所にブレイクポイントをしかけたところ、「Error uploading: Processing of multipart/form-data request failed.」というメッセージが生じていることを補足できました。
そのメッセージが生成されている場所を追いかけていくと、内部で使用しているApache Commons FileUploadでなにかが起きているところまで辿り着くことができました。

org.apache.commons.fileupload.FileUploadBaseクラスのparseRequestメソッド内で、Streams#copyを使ってHTTPリクエストからの入力ストリームをテンポラリファイル書き出すところで、java.io.IOExceptionが発生し処理が止まります。
例外処理の中ではキャッチしたIOExceptionからgetMessageメソッドで具体的な内容を取得してメッセージ化し、それをorg.apache.commons.fileupload.FileUploadBase.IOFileUploadExceptionに込めてスローさせるので、意図からすると呼び出し側ではスローされた例外を見れば原因がわかりそうです。
しかし、IOFileUploadExceptionのメッセージを見るとnullが設定されており原因は把握できません。(他のケースでは実装者の意図通り原因が表示されるようです。)
そこで、ここにブレイクポイントをしかけると、IOExceptionの具体的な中身はEOFExceptionであることがわかります。
入力ストリームの内容を出力ストリームに送る機能でEOFExceptionが出るということは、ブラウザ側がきちんとデータを送っていないか、間に挟まっているフレームワークが悪さをしているかがまず思い浮かびます。
処理の都合上jQuery.ajax()を使って実装していることも原因として充分に怪しいのですが、直前に対処した問題がまさに後者のパターンであったため、これなのではないかと推測、そして深みへとはまります。

補足したメッセージをネットで検索をしてみるとApache Commons FileUploadのトラッキングサイトに「FILEUPLOAD-262 Processing of multipart/form-data request failed. null」という今回の事象まんまで2014年11月にバグレポートが上がっているものの、未解決状態のまま放置されています。プライオリティもMinor扱い。

とりあえず、事象とキーワードがわかったので、適当な語句を選んで検索を仕掛けてみると、類似する事象はいくつか見つかるのですが、どれもこれも原因と対策がセットになった結論まではでていません。
みんなお手上げ状態なのでしょうか…

普段使わないような設定を変えてみたり、ライブラリに依存しないよう自前のルーチンに置き換えてみたりいろいろと試してみたのですが、原因はもっと単純なところにあった、というしょうもないオチでした。


2017/05/15 追記

Subversionをweb経由で使用していて、Apacheのログに「Could not get next bucket brigade」という記載があった場合、これもESETが原因である可能性があります。
ESETのWebアクセス保護機能を止めたところ問題なく処理が完了するようになりました。

また、きちんと再現テストはしていないのですが「ModSecurity: Error reading request body: Partial results are valid but processing is incomplete」「ModSecurity: Request body (Content-Length) is larger than the configured limit」といった内容が記載がされた場合もESETに起因する可能性がありそうな。

makoto について

デジタルガジェット大好き!! 小さい機械を片手に、JavaとFlex、PHPなど、いろいろなプログラミング言語・環境を行ったり来たりしながらプログラムを書いています。 最近お気に入りな環境は、Visual StudioとFileMaker。
カテゴリー: Java, システム開発, セキュリティ, 技術的なメモ タグ: , , , , パーマリンク