我正在尝试使用 Java 的 HttpURLConnection 进行“条件获取”,但我从未收到 304 状态代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7095897/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
I'm trying to use Java's HttpURLConnection to do a "conditional get", but I never get a 304 status code
提问by sanity
Here is my code:
这是我的代码:
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
}
I never seem to get the HTTP_NOT_MODIFIED response code, even hitting the same server several times in quick succession - where there is definitely no change to the page. Also, conn.getHeaderField("ETag") always seems to respond null, and sometimes conn.getHeaderFieldDate("Last-Modified", 0) returns 0. I've tried this against a variety of web servers.
我似乎从来没有得到 HTTP_NOT_MODIFIED 响应代码,即使快速连续多次访问同一台服务器 - 页面绝对没有变化。此外, conn.getHeaderField("ETag") 似乎总是响应 null,有时 conn.getHeaderFieldDate("Last-Modified", 0) 返回 0。我已经针对各种 Web 服务器尝试过这个。
Can anyone tell me what I'm doing wrong?
谁能告诉我我做错了什么?
回答by BalusC
You're all dependent on the server config.
你都依赖于服务器配置。
If you get an Expires
response header, then it just means that you don't need to request anything until the specified expire time. If you get a Last-Modified
response header, then it means that you should be able to use If-Modified-Since
to test it. If you get an ETag
response header, then it means that you should be able to use If-None-Match
to test it.
如果你得到一个Expires
响应头,那么它只是意味着你不需要在指定的过期时间之前请求任何东西。如果你得到一个Last-Modified
响应头,那么这意味着你应该可以If-Modified-Since
用来测试它。如果你得到一个ETag
响应头,那么这意味着你应该可以If-None-Match
用来测试它。
Lets take http://cdn3.sstatic.net/stackoverflow/img/favicon.icoas an example (the Stackoverflow's favicon image):
让我们以http://cdn3.sstatic.net/stackoverflow/img/favicon.ico为例(Stackoverflow 的 favicon 图片):
URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
System.out.println(connection.getHeaderFields());
This gives:
这给出:
{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]}
{null=[HTTP/1.1 200 OK],ETag=["9d9bd8b1165cb1:0"],日期=[2011 年 8 月 17 日星期三 17:57:07 GMT],内容长度=[1150],上次修改=[ 2010 年 10 月 6 日星期三 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]}
Now, do a If-Modified-Since
with the same value as Last-Modified
:
现在,使用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());
This gives as expected a 304:
正如预期的那样,这给出了 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]}
{null=[HTTP/1.1 304 Not Modified], ETag=["9d9bd8b1165cb1:0"], Date=[Wed, 17 August 2011 17:57:42 GMT], Last-Modified=[Wed, 06 Oct 2010 02:格林威治标准时间 53:46],连接=[保持活动],服务器=[nginx/0.8.36],X-Cache=[HIT],Cache-Control=[max-age=604800]}
Now, do a If-None-Match
with the same value as ETag
:
现在,使用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());
This gives unexpectedlya 200:
这出乎意料地给出了 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]}
{null=[HTTP/1.1 200 OK],ETag=["9d9bd8b1165cb1:0"],日期=[2011 年 8 月 17 日星期三 18:01:42 GMT],内容长度=[1150],上次修改=[ 2010 年 10 月 6 日星期三 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]}
Even more surprising, when the both headers are set with random garbage value as ETag
, the server still gives a 304. This is an indication that the If-None-Match
is completely ignored by the server behind http://cdn3.sstatic.net. That might be a (proxy) configuration issue or be done fully awarely (not for obvious reasons imho).
更令人惊讶的是,当两个标头都设置为随机垃圾值时ETag
,服务器仍然给出 304。这表明http://cdn3.sstatic.netIf-None-Match
后面的服务器完全忽略了。这可能是(代理)配置问题,或者完全有意识地完成(不是出于显而易见的原因恕我直言)。
回答by fider
Or shorter :)
或更短:)
Just try set connection timeout other than 0.
只需尝试设置 0 以外的连接超时。
conn.setConnectionTimeout( 3000);
Do it after .openConnection()
在 .openConnection() 之后做
final HttpURLConnection conn = (HttpURLConnection) sourceURL.openConnection();
conn.setConnectionTimeout( 3000);
If not set also readTimeout other than 0.
如果未设置,则 readTimeout 也不是 0。
conn.setReadTimeout( 3000);