java - 我正在尝试使用 Java 的 HttpURLConnection 来执行 "conditional get",但我从未获得 304 状态代码

标签 java http caching http-caching

这是我的代码:

    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-SinceLast-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-MatchETag 具有相同的值:

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-Matchhttp://cdn3.sstatic.net 后面的服务器完全忽略.这可能是一个(代理)配置问题或完全有意识地完成(恕我直言,不是出于明显的原因)。

关于java - 我正在尝试使用 Java 的 HttpURLConnection 来执行 "conditional get",但我从未获得 304 状态代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7095897/

相关文章:

http - 检查 url 中的数据自上次以来是否已更改?

c - 使用填充防止虚假共享

java - 使用 visualvm 进行分析时如何避免出现类似 "Profiler Agent Warning: Failed to lookup cached class org/apache/derby..."的消息?

Java 性能 - 良好实践(使用引用资料)

java - 玩框架2.4 GlobalSettings。这里没有预期的界面

api - 用于添加/删除数组元素的 RESTful API 端点?

java - 是否有特定于 URL 的 hashCode 方法?

java - 在 JavaFX 中调用 swing 软件的 main 函数将终止 JavaFX 软件

java - 如何编写正则表达式以从字符串中删除所有字母字符

javascript - 如何优雅地将在线 JavaScript 依赖项添加到源代码中?