- PR -

Tomcatフィルターを通して、動画・音楽ファイルをリクエストした時に例外が発生する

投稿者投稿内容
未記入
会議室デビュー日: 2006/11/23
投稿数: 3
投稿日時: 2007-03-02 11:00
はじめまして。

現在、Tomcat認証フィルターを製造しているのですが、フィルターを通して動画・音楽
ファイルをダウンロード・ストリームしようとすると

「java.lang.IllegalStateException: レスポンスをコミットした後でフォワードできま
せん」

という例外が発生してしまいます。

doFilterのみを実行する(リクエストをそのまま素通りさせる)フィルターを作成して
実験してみても同様の例外が発生してしまいます。

認識としては、1度のレスポンスで送信しきれない大きいサイズのファイルを要求した
場合、複数リクエストが発生してしまい、前回のリクエストをdoFilterしている間に
次のリクエストが来てしまい、上記例外が発生してしまっているという事でしょうか?

認識違いかもしれませんが、これを上手く切り抜ける方法はありませんでしょうか?

ご存知の方いらっしゃいましたら、ご教授願います。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2007-03-02 11:20
レスポンスをコミット、というのはHTTPレスポンスちょっとでも返してしまったということです。

フォワードする前にバッファ以上にレスポンスに書き出したり、setError() とか flush() を呼び出したりすると発生します。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-03-02 11:21
HttpServletResponseからgetOutputStream()で取得したStreamに書き出しをはじめてから、
RequestDispatcher.forward()したりした場合に発生します。

意味はエラーメッセージ通り「レスポンスをコミットした後でフォワードできま
せん」ですね。
Filterの扱い方か、Servetでのデータの書き出し方に誤りがあるのではないでしょうか。
どこかしらで、データを書き出してからforwordしているのでしょうから、
そうならないように設計を見直しましょう、としか言えませんね…。
未記入
会議室デビュー日: 2006/11/23
投稿数: 3
投稿日時: 2007-03-02 12:05
早速のご教授ありがとうございます。

引用:

レスポンスをコミット、というのはHTTPレスポンスちょっとでも返してしまったということです。

フォワードする前にバッファ以上にレスポンスに書き出したり、setError() とか flush() を呼び出したりすると発生します。


インギさん
バッファ以上にレスポンスを書き出したりというのは、バッファ以上のデータが書き込まれてしまった場合、データが漏れ出してレスポンスを知らない間に返してしまっているという可能性は考えられますか?

引用:

どこかしらで、データを書き出してからforwordしているのでしょうから、
そうならないように設計を見直しましょう、としか言えませんね…。



nagiseさん
doFilterのみを実行する単純なフィルターで試してみても同様の結果でした。
となると、フィルター側ではなくフィルター対象サーブレット側が怪しそうですね。
ちなみに、例えば一度リクエストを返してしまった状態で、そのリクエストをキャンセルして、forwardしたりは出来ないものでしょうか?

山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2007-03-02 12:10
>バッファ以上にレスポンスを書き出したりというのは、バッファ以上のデータが書き込まれてしまった場合、
>データが漏れ出してレスポンスを知らない間に返してしまってい
漏れ出す、というかそれが仕様です。
forwardするなら書き出さない、書き出すなら forward しない、のが基本です。

>ちなみに、例えば一度リクエストを返してしまった状態で、そのリクエストをキャンセルして、forwardしたり
>は出来ないものでしょうか?
残念ですが、それが出来ない、というエラーメッセージです。
HTTP の仕様上無理です。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2007-03-02 12:16
一応、仕様のポインタを示しておきますね。
・JavaTM Servlet Specification Version 2.3 - SRV.5.1 Buffering P39

開発の際は仕様書を手元に置いておくことをオススメします。
http://jcp.org/aboutJava/communityprocess/final/jsr053/index.html
小僧
ぬし
会議室デビュー日: 2002/08/14
投稿数: 526
投稿日時: 2007-03-02 12:35
>ちなみに、例えば一度リクエストを返してしまった状態で、そのリクエストを
>キャンセルして、forwardしたりは出来ないものでしょうか?

フォーワードを行うかを判断するタイミングを遅らせることができるのならば、
キャンセルという処理を行わなくても済んだりしないですかね。ある程度ストリーム
に出力しなければ判断が付かないならば、判断するまではバッファに出力させて
おいて、クライアントには何も返さない状態を作ってしまうとか。

nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-03-02 14:18
引用:

未記入さんの書き込み (2007-03-02 12:05) より:
ちなみに、例えば一度リクエストを返してしまった状態で、そのリクエストをキャンセルして、forwardしたりは出来ないものでしょうか?



一度送出したHTTPパケットをキャンセルできるのであれば可能でしょう。
そう、インギさんもおっしゃるとおりHTTPの仕様上無理ですね。

擬似的にそれをやるのだとすれば、小僧氏がおっしゃるように
バッファリングして実際には出力しないようにしておいて、
つまり、実際のHTTPレスポンスが飛ばないようにしておいて
差し替えるような工夫が必要ですね。原理的には。

スキルアップ/キャリアアップ(JOB@IT)