为什么 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
的类型是什么(HttpUrlConnection
、URLConnection
等),它都会为 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();
}
}
我用这个
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
的类型是什么(HttpUrlConnection
、URLConnection
等),它都会为 headers 提供访问器。查看名为 *.eaders.*
的方法,例如:getHeaderFields()
.
相比之下,getInputStream()
可能只会阅读响应 body。
编辑 1:根据您更新的问题,很明显您正在使用 java.net.URLConnection
所以我原来的答案是:getInputStream()
只是阅读响应 body 并且您将从 getHeaderFields()
.
修改后的问题还明确指出,您不仅对 如何 获得 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();
}
}