2013-08-28 3 views
8

私のアプリケーションは、後続のgetParameter呼び出しの結果を変更せずにPOSTリクエストのcontent/data/body/payloadを検査する必要がある状況にあります。 InputStreamの本体を読み取るHTTPServletRequestのPOST本体を読み込んでから、TomcatでgetParameterを呼び出します。

体はrequest.getReaderからrequest.getInputStream又はBufferedReaderのからの入力ストリームを使用して読み取ることができます。

読書POSTパラメータ:

POSTリクエストは、通常、要求のボディにリクエストパラメータを含みます。これらはgetParameterを使用して取得できます。

問題:

最初getParameterコールは、内部InputStreamを解析し、パラメータのHashMapに全てのパラメータを挿入します。 inputStreamには解析のための内容がまだ含まれている必要があります。したがって、コンテンツを検査することはできず、まだ動作しているgetParameter呼び出しがあります。

提案(しかし、十分ではない)ソリューション

InputStreamをキャッシュしてのgetInputStreamのキャッシュを返す要求ラッパーを作成します。

getParameterは実際にはgetInputStreamを呼び出すのではなく、要求オブジェクトに埋め込まれている元のinputBufferを参照するため、このソリューションはWeb上で提案されていますが、機能しません。サーブレット内とフィルタを使用して試しました。

私が考えることができる唯一の解決策は、実際にキャッシュされた入力ストリームを手動で解析するようにgetParameterを書き直すことです。しかし、これは悪い考えのように感じます。

誰にでも動作する代替手段はありますか? (これはTomcat 5.5です)これは一般的な使用事例であるように感じます。私はそれがどれほど難しいか信じられない。

+1

この質問に対する答えは解決策ではありません。私はそれを実装しましたが、問題を解決できませんでした。それ以来、私はtomcatのソースを読んで、getParameterはgetInputStreamを呼び出さないことに気付きました。私は上記のように、キャッシュされたストリームのストリームから読み込みません。 http://grepcode.com/file/repo1.maven.org/maven2/tomcat/catalina/5.5.23/org/apache/catalina/connector/RequestFacade.java?av=f#342を参照してください。 私はありませんなぜ人々はそれが解決策であることが分かったのでしょうか。 – rewolf

+0

メソッド 'getParameter'は' getInputStream'を呼び出します。まず、 'getParameter'は' parseParameters'を呼び出し、次に 'parseParameters'は' readPostBody'を呼び出し、 'readPostBody'は' getInputStream'を呼び出します。 – peakmuma

答えて

1

@caskeyで提案されているように、リフレクションを使用してinputBufferを再生可能な入力バッファで置き換えることが考えられます。しかし、私はそれがいたずらに感じるので、そのアプローチを使用しませんでした。

代わりに、入力ストリームをバイト配列に読み込み、getInputStreamの呼び出しでその配列の内部でByteArrayInputStreamを内部的に使用する新しいInputStreamを返すフィルタで要求ラッパーを作成しました。

入力ストリームをバイト配列に読み込んだ後、ペイロードを解析してパラメータマップを作成します。スーパークラスのパラメータマップをマージして、GETケースをクエリパラメータでサポートしました。このパラメータマップを使用するには、すべてのgetParameter *()メソッドをオーバーライドしました。

apache.axis.utils.IOUtils.readFullyを使用して、ストリームをバイト配列に読み込みやすくしました。私は現在javax.servlet.http.HttpUtils.parsePostDataを使ってデータをパラメータマップに解析しています。 HttpUtils.parsePostDataは実際には推奨されていませんので、見つけたら、より良いバージョンに置き換えてください。

しかし、これはうまく動作します。

1

(それはかなり古いTomcatの、私はより現代的なものにアップグレードすることを仮定していることはオプションではありません。)

あなたが何をしたいのか根本的に包むコンクリートHttpServletResponseオブジェクトの構築を遮断する必要がありますInputStream。プッシュバック入力ストリーム(または同等のもの)にInputStreamをラップする必要があります。

Tomcat 5.5は古くから私はそれがどのように「普通に」成し遂げられるのか考えることさえできませんが、具体的なリクエストオブジェクトの中でInputStreamオブジェクトに入り込みスワップするためにリフレクションを使用するフィルタを書くことができます。

+0

うん。あなたは反射のアイデアにかなり魅力的です。私たちはまたそれを考え出した。私は、入力ストリームの再生をサポートするフィルタにリクエストラッパーを作成するという別のアプローチを採用することを選択しました。次に、getParameter *()メソッドをオーバーライドして、入力ストリーム/ペイロードの解析によって作成されたマップから読み込みます。 – rewolf

関連する問題