为什么 URLConnection.getInputStream() 不包含 HTTP 响应 headers?

Why does URLConnection.getInputStream() not include the HTTP response headers?

我用这个

public static final String LOGIN_URL = "http://www.icourse163.org/passport/reg/icourseLogin.do";

public static void loginSimulation() throws IOException {
    URL loginUrl = new URL(LOGIN_URL);
    URLConnection connection = loginUrl.openConnection();
    connection.setRequestProperty("User-Agent",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36");
    connection.setRequestProperty("Accept",
            "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
    connection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
    connection.setRequestProperty("Connection", "keep-alive");
    connection.setRequestProperty("Referer", "http://www.icourse163.org/member/logout.htm");
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    connection.setDoOutput(true);

    PrintWriter loginDataWriter = new PrintWriter(connection.getOutputStream());

    String loginData = "returnUrl=aHR0cDovL2ljb3Vyc2UxNjMub3JnLw%3D%3D&failUrl=aHR0cDovL3d3dy5pY291cnNlMTYzLm9yZy9tZW1iZXIvbG9naW4uaHRtP2VtYWlsRW5jb2RlZD1PVGM1TnpJME9EZ3lRSEZ4TG1OdmJRPT0%3D&savelogin=false&oauthType=&username=979724882%40qq.com";
    loginDataWriter.print(loginData);
    loginDataWriter.flush();



    BufferedReader reader = new BufferedReader(
            new InputStreamReader(connection.getInputStream()));
    StringBuilder builder = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null){
        builder.append(line);
    }

但是 builder.toString 没有关于响应 headers 的任何信息?我认为我的客户端和服务器之间有一条管道。所以所有的响应都应该通过这个管道(包括响应 headers、响应内容等)。但结果不是。为什么?

无论 connection 的类型是什么(HttpUrlConnectionURLConnection 等),它都会为 headers 提供访问器。查看名为 *.eaders.* 的方法,例如:getHeaderFields().

相比之下,getInputStream() 可能只会阅读响应 body。

编辑 1:根据您更新的问题,很明显您正在使用 java.net.URLConnection 所以我原来的答案是:getInputStream() 只是阅读响应 body 并且您将从 getHeaderFields().

获得 HTTP 响应 headers

修改后的问题还明确指出,您不仅对 如何 获得 headers 感兴趣,而且对 为什么 感兴趣headers 在 InputStream 中不可用。在您的客户端和原始 HTTP 响应之间有一个库,该库决定以这种方式向您呈现原始响应:(1) 响应 body 作为 InputStream; (2)把headers当成Map<String,List<String>>。这是在该库的实现中做出的选择。因此,只要您使用 java.net.URLConnection 这就是您必须使用响应的方式。 FWIW,其他库(例如 Apache Commons 的 HttpClient)也做同样的事情。

您应该使用 getHeaderFields 获取响应 headers。

你可以这样试试吗

import java.net.*;
import java.io.*;

public class URLConnectionReader {
public static void main(String[] args) throws Exception {
    URL oracle = new URL("http://www.oracle.com/");
    URLConnection yc = oracle.openConnection();
    BufferedReader in = new BufferedReader(new InputStreamReader(
                                yc.getInputStream()));
    String inputLine;
    while ((inputLine = in.readLine()) != null) 
        System.out.println(inputLine);
    in.close();
    }

}