我正在编写一种资源处理方法,我可以控制对各种文件的访问,我希望能够使用浏览器的缓存。 我的问题是双重的:

  1. 哪些是确定的HTTP标头,我需要检查以确定是否应该发送304响应,以及当我检查它时我在寻找什么?

  2. 另外,当我最初发送文件(如'Last-Modified')作为200响应时,是否需要发送任何标头?

一些伪代码可能是最有用的答案。


缓存控制头怎么样? 可能的各种可能值会影响您发送给客户端的内容(即max-age),还是应该只有在被修改后才能遵守?

===============>>#1 票数:8 已采纳

这是我实现它的方式。 代码已经工作了一年多,并且有多个浏览器,所以我认为它非常可靠。 这基于RFC 2616并通过观察各种浏览器发送的内容和时间。

这是伪代码:

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

if etag_from_browser does not exist:
    etag_from_browser = get_header("If-None-Match")
if the browser has quoted the etag:
    strip the quotes (e.g. "foo" --> foo)

set server_etag into http header

if etag_from_browser matches server_etag
    send 304 return code to browser

这是我的服务器逻辑片段,用于处理此问题。

/* the client should set either Etag or If-None-Match */
/* some clients quote the parm, strip quotes if so    */
mketag(etag, &sb);

etagin = apr_table_get(r->headers_in, "Etag");
if (etagin == NULL)
    etagin = apr_table_get(r->headers_in, "If-None-Match");
if (etag != NULL && etag[0] == '"') {
    int sl; 
    sl = strlen(etag);
    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) {
    /* if the etag matches, we return a 304 */
    rc = HTTP_NOT_MODIFIED;
}

如果你想在etag生成方面获得一些帮助,可以发布另一个问题,我也会挖出一些代码来解决这个问题。 HTH!

===============>>#2 票数: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部分的最小努力方法,找出可以在Web应用程序中轻松正确生成哪些(Expires,ETag和Last-Modified)标头。

对于建议的阅读材料:

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

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

===============>>#3 票数:3

如果客户端明确声明它可能已经在其缓存中有页面,则应发送304。 这称为条件GET,它应在请求中包含if-modified-since标头。

基本上,此请求标头包含客户端声称拥有缓存副本的日期。 您应该检查此日期之后内容是否已更改,如果没有,则发送304。

有关RFC中的相关部分,请参见http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25

===============>>#4 票数:2

我们还处理缓存但安全的资源。 如果您发送/生成ETAg标头(RFC 2616第13.3节建议您应该),那么客户端必须在条件请求中使用它(通常在If-None-Match - HTTP_IF_NONE_MATCH - 标头中)。 如果你发送Last-Modified标题(你应该再次),那么你应该检查If-Modified-Since - HTTP_IF_MODIFIED_SINCE - 标题。 如果你发送两个,那么客户端应该发送两个,但它必须发送ETag。 另请注意,验证仅定义为检查条件标头是否与您要发送的条件标头严格相等。 此外,只有强验证器(如ETag)才会用于远程请求(其中只请求部分资源)。

实际上,由于我们保护的资源是相当静态的,并且可以接受一秒的滞后时间,我们正在执行以下操作:

  1. 检查用户是否有权访问所请求的资源

    如果不是,请根据需要重定向或发送4xx响应。 我们将对看起来像黑客企图或公然尝试执行安全性结束运行的请求生成404响应。

  2. 将If-Modified-Since标头与Last-Modified标头进行比较,我们将发送(见下文)严格相等

    如果匹配,则发送304 Not Modified响应并退出页面处理

  3. 使用所请求资源的修改时间创建Last-Modified标头

    在RFC 2616中查找HTTP日期格式

  4. 发送标头和资源内容以及适当的Content-Type

我们决定避开ETag标题,因为它对我们来说是过度的。 我想我们也可以使用日期时间戳作为ETag。 如果我们转移到一个真正的ETag系统,我们可能会为资源存储计算的哈希值,并将它们用作ETag。

如果您的资源是动态生成的,例如数据库内容,那么ETag可能更适合您的需求,因为它们只是您认为合适的文本。

===============>>#5 票数:1

关于缓存控制:

除了将其设置为合理的值之外,您不必在服务时担心缓存控制。 它基本上告诉浏览器和其他下游实体(例如代理)在超时缓存之前应该经过的最长时间。

  ask by tags2k translate from so

未解决问题?本站智能推荐: