11

さまざまなファイルへのアクセスを制御するリソース処理メソッドを作成しており、ブラウザのキャッシュを利用できるようにしたいと考えています。私の質問は 2 つあります。

  1. 304 応答を送信する必要があるかどうかを確実に知るために確認する必要がある決定的な HTTP ヘッダーはどれですか?また、それらを確認するときに何を探していますか?

  2. さらに、最初にファイルを送信するときに (「Last-Modified」など) 200 応答として送信する必要があるヘッダーはありますか?

疑似コードがおそらく最も有用な答えになるでしょう。


cache-control ヘッダーはどうですか? そのさまざまな可能な値は、クライアントに送信するもの (つまり max-age) に影響を与えることができますか、それとも if-modified-since に従う必要がありますか?

4

5 に答える 5

8

これが私がそれを実装した方法です。コードは 1 年以上にわたって複数のブラウザーで動作しているので、かなり信頼できると思います。これは、 RFC 2616に基づいており、さまざまなブラウザーが何をいつ送信したかを観察することによって行われます。

擬似コードは次のとおりです。

server_etag = gen_etag_for_this_file(myfile)
etag_from_browser = get_header("Etag")

etag_from_browser が存在しない場合:
    etag_from_browser = get_header("If-None-Match")
ブラウザが etag を引用している場合:
    引用符を取り除きます (例: "foo" --> foo)

server_etag を http ヘッダーに設定する

etag_from_browser が server_etag と一致する場合
    304 リターン コードをブラウザに送信する

これを処理するサーバー ロジックのスニペットを次に示します。

/* クライアントは Etag または If-None-Match を設定する必要があります */
/* 一部のクライアントは parm を引用します。その場合は引用符を取り除きます */
mketag(etag, &sb);

etagin = apr_table_get(r->headers_in, "Etag");
if (エタジン == NULL)
    etagin = apr_table_get(r->headers_in, "If-None-Match");
if (etag != NULL && etag[0] == '"') {
    intsl;
    sl = strlen(エタグ);
    memmove(etag, etag+1, sl+1);
    etag[sl-2] = 0;
    logit(2,"etag=:%s:",etag);
}   
...
apr_table_add(r->headers_out, "ETag", etag);
...
if (etagin != NULL && strcmp(etagin, etag) == 0) {
    /* etag が一致する場合、304 を返します */
    rc = HTTP_NOT_MODIFIED;
}   

etag 生成に関するヘルプが必要な場合は、別の質問を投稿してください。それを行うコードも掘り下げます。チッ!

于 2008-08-07T08:30:16.113 に答える
4

304 Not Modified 応答は、If-Modified-Since (「IMS」) または If-Not-Match (「INM」) ヘッダーを使用した GET または HEAD 要求から生じる場合があります。

これらのヘッダーを受け取ったときに何をすべきかを決定するために、これらの条件ヘッダーなしで GET 要求を処理していると想像してください。ETag および Last-Modified ヘッダーの値がその応答でどのようなものになるかを判断し、それらを使用して決定を下します。これを決定するコストが、完全な応答を作成するコストよりも低くなるように、システムを構築したことを願っています。

INM があり、そのヘッダーの値が ETag に配置する値と同じである場合は、304 で応答します。

IMS があり、そのヘッダーの日付値が Last-Modified に配置するものよりも新しい場合は、304 で応答します。

それ以外の場合は、リクエストにそれらのヘッダーが含まれていないかのように続行します。

質問のパート 2 への最も簡単な方法として、(Expires、ETag、および Last-Modified) ヘッダーのうち、Web アプリケーションで簡単かつ正確に作成できるものを見つけてください。

推奨される読み物:

http://www.w3.org/Protocols/rfc2616/rfc2616.html

http://www.mnot.net/cache_docs/

于 2008-08-09T13:27:59.343 に答える
3

クライアントがキャッシュに既にページを持っている可能性があると明示的に述べている場合は、304 を送信する必要があります。これは条件付き GET と呼ばれ、要求にif-modified-sinceヘッダーを含める必要があります。

基本的に、この要求ヘッダーには、クライアントがキャッシュされたコピーがあると主張する日付が含まれています。この日付以降にコンテンツが変更されたかどうかを確認し、変更されていない場合は 304 を送信する必要があります。

RFC の関連セクションについては、http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25を参照してください。

于 2008-08-07T08:01:54.203 に答える
2

また、キャッシュされているが安全なリソースも処理しています。ETAg ヘッダー (RFC 2616 セクション 13.3 で推奨されている) を送信/生成する場合、クライアントはそれを条件付き要求 (通常は If-None-Match - HTTP_IF_NONE_MATCH - ヘッダー) で使用する必要があります。Last-Modified ヘッダーを送信する場合 (再度送信する必要があります)、If-Modified-Since - HTTP_IF_MODIFIED_SINCE - ヘッダーを確認する必要があります。両方を送信する場合、クライアントは両方を送信する必要がありますが、ETag を送信する必要があります。また、validtion は、条件付きヘッダーが送信するものと厳密に等しいかどうかをチェックするものとして定義されているだけであることに注意してください。また、強力なバリデーター (ETag など) のみが、範囲指定された要求 (リソースの一部のみが要求される場合) に使用されます。

実際には、保護しているリソースはかなり静的であり、1 秒のラグ タイムが許容されるため、次のことを行っています。

  1.  ユーザーが要求されたリソースへのアクセスを許可されているかどうかを確認します

         そうでない場合は、リダイレクトするか、必要に応じて 4xx 応答を送信します。ハッキングの試みやあからさまなセキュリティ エンド ランの実行を試みているように見える要求に対しては、404 応答が生成されます。

  2.  If-Modified-Since ヘッダーを、送信する Last-Modified ヘッダーと比較して (以下を参照)、厳密に等しいかどうかを確認します。

         一致する場合は、304 Not Modified 応答を送信し、ページ処理を終了します。

  3.  要求されたリソースの変更時刻を使用して Last-Modified ヘッダーを作成します

        RFC 2616 で HTTP 日付形式を調べる

  4.  適切な Content-Type とともにヘッダーとリソース コンテンツを送信する

We decided to eschew the ETag header since it is overkill for our purposes.  I suppose we could also just use the date time stamp as an ETag.  If we move to a true ETag system, we would probably store computed hashes for the resources and use those as ETags.

If your resources are dynamically generated, from say database content, then ETags may be better for your needs, since they are just text to be populated as you see fit.

于 2009-10-13T14:05:05.560 に答える
1

キャッシュ制御について:

適切な値に設定する以外は、サービスを提供するときにキャッシュ制御について心配する必要はありません。これは基本的に、キャッシュがタイムアウトするまでの最大経過時間をブラウザやその他のダウンストリーム エンティティ (プロキシなど) に伝えます。

于 2008-08-07T08:47:09.700 に答える