有没有办法获得原始响应http标头?
getHeaderField()
方法对我不起作用,因为服务器会发送多个“Set-Cookie”,其中一些会丢失。
答案 0 :(得分:31)
getHeaderField()
方法对我不起作用
你在java.net.URLConnection
的背景下问这个,是吗?不,URLconnection
无法获取原始HTTP响应标头。您需要回退到低级Socket编程。这是一个SSCCE,只是复制'n'paste'n'run它。
package com.stackoverflow.q2307291;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class Test {
public static void main(String[] args) throws IOException {
String hostname = "stackoverflow.com";
int port = 80;
Socket socket = null;
PrintWriter writer = null;
BufferedReader reader = null;
try {
socket = new Socket(hostname, port);
writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.println("GET / HTTP/1.1");
writer.println("Host: " + hostname);
writer.println("Accept: */*");
writer.println("User-Agent: Java"); // Be honest.
writer.println(""); // Important, else the server will expect that there's more into the request.
writer.flush();
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
for (String line; (line = reader.readLine()) != null;) {
if (line.isEmpty()) break; // Stop when headers are completed. We're not interested in all the HTML.
System.out.println(line);
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
if (writer != null) { writer.close(); }
if (socket != null) try { socket.close(); } catch (IOException logOrIgnore) {}
}
}
}
为了避免每个人尝试这个片段而导致SO超负荷,这里是输出的样子:
HTTP/1.1 200 OK Cache-Control: private Content-Type: text/html; charset=utf-8 Expires: Sun, 21 Feb 2010 20:39:08 GMT Server: Microsoft-IIS/7.5 Date: Sun, 21 Feb 2010 20:39:07 GMT Connection: close Content-Length: 208969
要了解有关以低级方式发送HTTP请求的详细信息,请阅读HTTP specification。
但是,您可能希望使用getHeaderFields()
方法来检索具有多个值的标头。根据链接的API文档,getHeaderField()
仅返回最后一个值。
List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
答案 1 :(得分:6)
不完全'原始'但简洁:
for (Map.Entry<String, List<String>> k : myHttpURLConnection.getHeaderFields().entrySet()) {
System.out.println(k.toString());
}
如果您担心某些标题丢失,请使用:
for (Map.Entry<String, List<String>> k : myHttpURLConnection.getHeaderFields().entrySet()) {
for (String v : k.getValue()){
System.out.println(k.getKey() + ":" + v);
}
}
PS:迟到总比没有好。 :)
答案 2 :(得分:2)
简单的方法是使用URLConnection
的{{3}}方法。这是一些代码相同的代码。
static String[] getHeaders(HttpURLConnection con, String header) {
List<String> values = new ArrayList<String>();
int idx = (con.getHeaderFieldKey(0) == null) ? 1 : 0;
while (true) {
String key = con.getHeaderFieldKey(idx);
if (key == null)
break;
if (header.equalsIgnoreCase(key))
values.add(con.getHeaderField(idx));
++idx;
}
return values.toArray(new String[values.size()]);
}
答案 3 :(得分:1)
晚会,但这是最简单的解决方案。只需实现CookieStore。 (或使用默认实现,并让它将cookie添加到您的后续调用中。)
http://docs.oracle.com/javase/7/docs/api/java/net/CookieStore.html
将您的cookie商店设置为默认Cookie管理器
CookieManager cookieManager = new CookieManager(new MyCookieStore(), CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);
每个新的cookie都会在你的CookieStore中的add()中出现。我在同一个请求中使用相同的名称“Set-Cookie”覆盖params也遇到了同样的问题,现在我同时获得了cookie和sessionId。