HttpURLConnection没有返回所有的头信息。

3
我正在使用以下代码打印HTTP头信息。
    URL url = new Url("htttp://example.com/example");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();

    Map<String, List<String>> map = conn.getHeaderFields();
    for (Map.Entry<String, List<String>> entry : map.entrySet()) {
        System.out.println("Key : " + entry.getKey() +
                " ,Value : " + entry.getValue());
    }

以下是输出结果:
Key : null ,Value : [HTTP/1.1 200 OK]
Key : Accept-Ranges ,Value : [bytes]
Key : Cache-Control ,Value : [max-age=604800, public]
Key : Connection ,Value : [Keep-Alive]
Key : Date ,Value : [Mon, 03 Oct 2016 18:01:06 GMT]
Key : ETag ,Value : ["159eb4-53dce1f957880-gzip"]
Key : Expires ,Value : [Mon, 10 Oct 2016 18:01:06 GMT]
Key : Keep-Alive ,Value : [timeout=5, max=100]
Key : Last-Modified ,Value : [Sat, 01 Oct 2016 13:59:46 GMT]
Key : Server ,Value : [Apache/2.4.12 (Unix) OpenSSL/1.0.1e-fips mod_bwlimited/1.4]
Key : Transfer-Encoding ,Value : [chunked]
Key : Vary ,Value : [Accept-Encoding,User-Agent]

现在我正在尝试使用curl:
$ curl -v -D - http://example.com/example -o /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 111.111.111.111...
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0* Connected to example.com (111.111.111.111) port 80 (#0)
> GET example.com/example HTTP/1.1
> Host: example.com
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Date: Mon, 03 Oct 2016 18:25:11 GMT
Date: Mon, 03 Oct 2016 18:25:11 GMT
< Server: Apache/2.4.12 (Unix) OpenSSL/1.0.1e-fips mod_bwlimited/1.4
Server: Apache/2.4.12 (Unix) OpenSSL/1.0.1e-fips mod_bwlimited/1.4
< Last-Modified: Sat, 01 Oct 2016 13:59:46 GMT
Last-Modified: Sat, 01 Oct 2016 13:59:46 GMT
< ETag: "159eb4-53dce1f957880"
ETag: "159eb4-53dce1f957880"
< Accept-Ranges: bytes
Accept-Ranges: bytes
< Content-Length: 1416884
Content-Length: 1416884
< Cache-Control: max-age=604800, public
Cache-Control: max-age=604800, public
< Expires: Mon, 10 Oct 2016 18:25:11 GMT
Expires: Mon, 10 Oct 2016 18:25:11 GMT
< Vary: Accept-Encoding,User-Agent
Vary: Accept-Encoding,User-Agent

< 
{ [1080 bytes data]
 30 1383k   30  427k    0     0   116k      0  0:00:11  0:00:03  0:00:08  116k^C

你看java输出中为什么缺少Content-Length头部信息?这是为什么?我该如何解决?


它是通过API提供的。没有固定的解决方案,也不需要一个。 - user207421
@EJP,为什么我不需要修复?如果服务器发送了“Content-Length”,API不应该返回“Content-Length”吗? - Binoy Babu
我所指的API是getContentLength()(和getContentLengthLong())。 - user207421
尝试调用 conn.setInstanceFollowRedirects(false) 看看能否解决问题。 - Nicolas Filotto
@EJP @NicolasFilotto getContentLength() 返回 -1。 - Binoy Babu
显示剩余5条评论
3个回答

4

Content-Length缺失是因为服务器以块的形式发送响应。这是预期的行为。查看Java响应中的Transfer-Encoding头,这里是RFC 2616, 4.4 消息长度(请参见列表的第3项)。


那么我该如何禁用它呢? - Binoy Babu
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - nandsito
@BinoyBabu RFC 2616, 14.41 表示“许多旧的 HTTP/1.0 应用程序不理解 Transfer-Encoding 标头”,因此,如果您可以配置服务器并真正希望禁用 Transfer-Encoding,则可以将服务器回滚到 HTTP/1.0,但我强烈不建议这样做,因为您将失去许多 1.1 的改进,例如 Transfer-Encoding 本身。 - nandsito
@BinoyBabu 你需要找到其他方法来确定实体主体的大小,例如下载所有内容并在此之后计算八位字节的数量,而不是观察“Content-Length”标题。 - nandsito
@BinoyBabu 要显示下载进度,您需要进行一些服务器配置,以确保它不会将响应分成块,因此响应将作为整体发送,并带有 Content-Length。否则将无法实现下载进度。 - nandsito
显示剩余2条评论

2

我没有解释为什么content-length不在头部中,如果该头不存在,则会返回-1,这就是这里的情况。 - Nicolas Filotto
@NicolasFilotto 根据 curl 的输出,如果头部没有被发送,它将返回-1,但这里不是这种情况。 - user207421
@EJP 不是的,我刚刚测试了使用Curl对www.google.com进行请求,我看到Content-Length为258,但是在Java中这个标头不在列表中,因此当我调用此方法时,返回值是-1。 - Nicolas Filotto
@NicolasFilotto 所以在 Java 的情况下由于某些原因它没有被发送。 - user207421

0

在Java中,响应包含“transfer-encoding”头,在curl响应中缺少该头。当我尝试时,我的尝试返回404(未找到)。当我从浏览器尝试时,也会返回404。

我猜测您已经覆盖了example.com的主机条目,将其循环回到您自己的Tomcat或类似服务上。这是您环境的问题。

这是我得到的:

    /**
     *
     * <P> jdk-1.8 </P>
     * <PRE>
Key :null || Values :[HTTP/1.1 404 Not Found]
Key :X-Cache || Values :[HIT]
Key :Server || Values :[ECS (ewr/1445)]
Key :Etag || Values :["359670651+gzip+ident"]
Key :Cache-Control || Values :[max-age=604800]
Key :x-ec-custom-error || Values :[1]
Key :Vary || Values :[Accept-Encoding]
Key :Last-Modified || Values :[Fri, 09 Aug 2013 23:54:35 GMT]
Key :Expires || Values :[Mon, 10 Oct 2016 19:20:29 GMT]
Key :Content-Length || Values :[1270]
Key :Date || Values :[Mon, 03 Oct 2016 19:20:29 GMT]
Key :Content-Type || Values :[text/html]
     * </PRE>
     * @param urlStr (http://example.com/example)
     */
    private static void printHeaders(String urlStr) {

        try {
            URL urlRef = new URL(urlStr);
            URLConnection urlConnection = urlRef.openConnection();
            Map<String, List<String>> headerFields = urlConnection.getHeaderFields();

            for (String headerName : headerFields.keySet()) {
                List<String> headerEntry = headerFields.get(headerName);
                System.out.println("Key :"+headerName +" || Values :"+headerEntry);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接