2

応答ヘッダーが 304 応答にしか表示されないというばかげた問題があります。私が使用しているサーバーは Tomcat 7 です。Java フィルターには次のコードが含まれています。

HttpServletResponse httpResponse = (HttpServletResponse) response;

httpResponse.addHeader("Access-Control-Allow-Origin", "*");
httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
httpResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
httpResponse.addHeader("Access-Control-Allow-Headers", "Content-Type, Accept");

if (debug) {
    httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1
    httpResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0
    httpResponse.setDateHeader("Expires", 0); // Proxies.
} else {
    httpResponse.setHeader("Cache-Control", "public");
    httpResponse.setDateHeader("Expires", System.currentTimeMillis() + 86400000L); // 1Day 
}

このフィルターはチェーン内で最後に起動されることに注意することが重要です。これは web.xml でマップされる最初のフィルターであり (最後のフィルターであっても違いはありません)、上記のコードはその後に実行されます。

chain.doFilter(request, response);

Chrome の監査ツールを使用してヘッダーを評価すると、200 でヘッダーが応答に含まれていないことに気付きました。「F5」を押してページを更新すると、304 が表示され、ヘッダーが表示されます。同様に、もう一度更新すると、ヘッダーが表示されない 200 が表示されます。ページを繰り返し更新すると、304 と 200 の応答が交互に表示され、304 ごとにヘッダーが表示されますが、200 には表示されません。

フィルターはすべてのリソースにマップされます。

<filter-mapping>
    <filter-name>AllowRemoteAccessHeaderFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>HttpCachingFilter</filter-name>
    <url-pattern>*</url-pattern>
</filter-mapping>

さらに、フィルターは、応答に関係なく、更新のたびに起動します。

誰かがここで実際に何が起こっているのか説明できますか? 私は小さな何かが欠けていると確信しています。私の目標は、200 応答のヘッダーをそこに置くことです。

編集:これは最初にロードされたページでは機能しますが、そのページにロードされたリソースは機能しないことに注意してください。スクリプト、画像、CSS が含まれます。

編集:ページからすべてのスクリプトレットを削除すると、ヘッダーが通過することにも気付きました。2 つのスクリプトレットにはそれぞれ、別のフィルターを介して要求オブジェクトに設定されたデータが含まれています。コンパイルされた JavaScript を挿入する例を以下に示します。

<script type="text/javascript"><%= request.getAttribute("compiled-scripts")%></script>

問題: 問題の原因はわかったかもしれませんが、解決策は見つかりませんでした。コンパイルされたスクリプトをページに含めると、転送エンコーディングが変更され、コンテンツの長さが次のように設定されます。

Transfer-Encoding:chunked

転送エンコーディングがチャンクされた瞬間、ヘッダーは通過しません。これは、コンテンツの長さが既知であり、設定されているため、304 で応答ヘッダーが通過する理由を説明している可能性があります。200 では、コンテンツの長さが不明であり、転送エンコーディングがチャンクされます。

しかし、私の問題はまだ残っています。遅延やその他の理由を減らすために、スクリプトを参照するのではなく、コンパイルされたスクリプトを含めたいと考えています。転送エンコードのチャンクを防ぐには、応答をバイト単位で読み取ることにより、コンテンツの長さを手動で設定する必要があることを読みました。フィルターで応答の長さを決定する方法がわかりません。

転送エンコーディングがチャンクされているときに、応答ヘッダーを通過させることは可能ですか?

4

2 に答える 2

0

私は最終的に答えを見つけました。この投稿のヒントに感謝します: JSP でバッファーと自動フラッシュの属性を変更する必要があるのはなぜですか?

より具体的にはこれ

バッファーが 1 回フラッシュされると、HTTP 応答ヘッダーに対するすべての変更は、バッファーがクライアントに最初に送信されるときに発生する必要があるため、リダイレクトまたは転送は機能しません。

chain.doFilter() の後に応答ヘッダーが設定されていたため、問題が発生していました。chain.doFilter() を呼び出す前にヘッダーを設定することで、問題は解決されました。応答ヘッダーがすべての要求と応答コードで通過していたことを意味します。

私の理解では、この場合のようにバッファがいっぱいになると、フラッシュされます。これにより、チャンク応答が発生します。ただし、バッファがフラッシュされる時点では、ヘッダーは設定されていません。ブラウザーは最初のチャンクから応答ヘッダーを差し引いたものを受け取り、最初のチャンクのヘッダーのみをチェックします。したがって、バッファがフラッシュされる前に応答ヘッダーを設定することにより、ブラウザは最初のチャンクでヘッダーを受け取ります。

于 2013-11-07T06:43:22.920 に答える