这是我的代码:
final HttpURLConnection conn = (HttpURLConnection) sourceURL.openConnection();
if (cachedPage != null) {
if (cachedPage.eTag != null) {
conn.setRequestProperty("If-None-Match", cachedPage.eTag);
}
conn.setIfModifiedSince(cachedPage.pageLastModified);
}
conn.connect();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
newCachedPage.eTag = conn.getHeaderField("ETag");
newCachedPage.pageLastModified = conn.getHeaderFieldDate("Last-Modified", 0);
} else if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
// Never reaches here
}
我似乎从来没有得到 HTTP_NOT_MODIFIED 响应代码,甚至连续多次访问同一台服务器 - 页面肯定没有变化。此外,conn.getHeaderField("ETag") 似乎总是响应 null,有时 conn.getHeaderFieldDate("Last-Modified", 0) 返回 0。我已经针对各种 Web 服务器尝试过此方法。
谁能告诉我我做错了什么?
最佳答案
你都依赖于服务器配置。
如果你得到一个Expires
响应头,那么它只是意味着你不需要在指定的过期时间之前请求任何东西。如果你得到一个 Last-Modified
响应头,那么这意味着你应该能够使用 If-Modified-Since
来测试它。如果你得到一个 ETag
响应头,那么这意味着你应该能够使用 If-None-Match
来测试它。
我们取 http://cdn3.sstatic.net/stackoverflow/img/favicon.ico作为示例(Stackoverflow 的网站图标图像):
URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
System.out.println(connection.getHeaderFields());
这给出:
{null=[HTTP/1.1 200 OK], ETag=["9d9bd8b1165cb1:0"], Date=[Wed, 17 Aug 2011 17:57:07 GMT], Content-Length=[1150], Last-Modified=[Wed, 06 Oct 2010 02:53:46 GMT], Content-Type=[image/x-icon], Connection=[keep-alive], Accept-Ranges=[bytes], Server=[nginx/0.8.36], X-Cache=[HIT], Cache-Control=[max-age=604800]}
现在,做一个 If-Modified-Since
与 Last-Modified
具有相同的值:
URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
connection.setRequestProperty("If-Modified-Since", "Wed, 06 Oct 2010 02:53:46 GMT");
System.out.println(connection.getHeaderFields());
这给出了预期的 304:
{null=[HTTP/1.1 304 Not Modified], ETag=["9d9bd8b1165cb1:0"], Date=[Wed, 17 Aug 2011 17:57:42 GMT], Last-Modified=[Wed, 06 Oct 2010 02:53:46 GMT], Connection=[keep-alive], Server=[nginx/0.8.36], X-Cache=[HIT], Cache-Control=[max-age=604800]}
现在,做一个 If-None-Match
与 ETag
具有相同的值:
URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
connection.setRequestProperty("If-None-Match", "9d9bd8b1165cb1:0");
System.out.println(connection.getHeaderFields());
这给了意外 200:
{null=[HTTP/1.1 200 OK], ETag=["9d9bd8b1165cb1:0"], Date=[Wed, 17 Aug 2011 18:01:42 GMT], Content-Length=[1150], Last-Modified=[Wed, 06 Oct 2010 02:53:46 GMT], Content-Type=[image/x-icon], Connection=[keep-alive], Accept-Ranges=[bytes], Server=[nginx/0.8.36], X-Cache=[HIT], Cache-Control=[max-age=604800]}
更令人惊讶的是,当两个 header 都设置了随机垃圾值作为 ETag
时,服务器仍然给出 304。这表明 If-None-Match
被 http://cdn3.sstatic.net 后面的服务器完全忽略.这可能是一个(代理)配置问题或完全有意识地完成(恕我直言,不是出于明显的原因)。
关于java - 我正在尝试使用 Java 的 HttpURLConnection 来执行 "conditional get",但我从未获得 304 状态代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7095897/