我能否在使用Java的HttpUrlConnection类时覆盖Host头?

30

我正在使用以下代码在Java中打开HTTP连接:

 URL url = new URL("http://stackoverflow.com");
 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 conn.setDoOutput(true);
 conn.setRequestMethod("GET");
 conn.setRequestProperty("Host", "Test:8080");
 conn.getOutputStream();

无论我以何种顺序调用方法,使用conn.setRequestProperty("Host", "Test:8080")似乎没有任何效果,并且主机名会被重置为目标服务器。是否有办法在不使用其他库的情况下覆盖主机头?

TIA Matt

3个回答

41
这在过去是有效的,但由于安全修复的一部分已被禁用。显然在更改日志中没有注释。甚至还有像#7022056这样的错误在bugs.sun.com上。
另一个标题有一个类似的问题,答案更详细,所以我只是链接它而不是自己写。 :-)
唯一的解决方法似乎是将sun.net.http.allowRestrictedHeaders设置为true,或者使用另一个HTTP库,如已经提到的http components

15
谢谢,System.setProperty("sun.net.http.allowRestrictedHeaders", "true") 很好地解决了问题。 - Pete Doyle
1
啊,刚刚花了几个小时调试并寻找答案!非常感谢。 - XXL
没错,System.setProperty("sun.net.http.allowRestrictedHeaders", "true") 的效果非常好。 - Nathan B

8
Host头部是由基于URL的HttpURLConnection填充的。您不能使用Host=bar.com打开foo.com。根据RFCHost请求头字段指定被请求资源的Internet主机和端口号,这些信息通常从用户或引用资源(一般是HTTP URL)提供的原始URI中获得。
另外,您也可以尝试使用Apache Http Components

2
谢谢,它可能符合RFC标准,但对我来说并不是很有帮助,因为我正在尝试实现一个反向代理,需要修改主机头上的端口,因为目标服务器期望进行端口映射。 - Matt
你可以尝试使用Apache Http Components。 - Bozho
1
一般而言我同意,但你可能需要连接到一个奇怪的远程系统,它不受你控制且没有DNS条目,但仍需要正确的主机头,因为它有虚拟主机。可悲的是,今天我遇到了这样的情况,但我希望(为了所有其他人的利益)这种情况真的很少见。;-) - Boris

-2
这是有关Volley如何处理HTTPUrlConnection和重试策略的问题。
解决方法是扩展“HurlStack”类,并覆盖“createConnection”函数,以返回一个ChunkStreamMode为0的HTTPUrlConnection。
public class CustomHurlStack extends HurlStack {


   public CustomHurlStack(){
       super();

   }

   @Override
   protected HttpURLConnection createConnection(URL url) throws IOException {
       HttpURLConnection connection = super.createConnection(url);
       connection.setChunkedStreamingMode(0);
       return connection;
   }

}


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