【发布时间】:2014-02-12 17:47:51
【问题描述】:
以下代码安全吗:
try {
URL url = new URL(urlRequest);
conn = (HttpURLConnection)url.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
String encoding = conn.getContentEncoding();
return Utils.wrapCompressedStream(conn.getInputStream(), encoding);
} catch (IOException e) {
if(conn != null) {
conn.getContentEncoding();
conn.getErrorStream();
conn.whateverOtherMethodThere();
...
}
}
特别是,在 InterruptedIOException(例如,读取超时)的情况下调用 getContentEncoding() 之类的方法是否安全?据我了解,此方法需要实时连接才能读取 HTTP(S) 标头。
更新(附加信息):
这个问题源于真实系统的体验。我相信,该系统当时是在 Oracle/Sun JVM 1.6 上运行的。代码几乎一样:
...
} catch (IOException e) {
if(conn != null) {
try {
String response = tryGetResponse(conn);
...
问题发生在 HTTPS 请求上的tryGetResponse:
private static String tryGetResponse(HttpURLConnection conn) {
if(conn == null) return "(failed to get)";
InputStream in = null;
try {
InputStream err = conn.getErrorStream();
if (err != null) {
in = Utils.wrapCompressedStream(err, conn.getContentEncoding());
}
return Utils.inputStreamToString(in);
} catch (IOException e) {
return "(failed to get)";
} finally {
Utils.closeQuitely(in);
}
}
在getContentEncoding() 调用中,系统自发挂起连接(或读取)套接字:
in = Utils.wrapCompressedStream(err, conn.getContentEncoding());
恰好在初始代码中抛出SocketTimeoutException 之后。
因此,getContentEncoding() 似乎尝试(或在 Java 6 中尝试)建立新连接而没有设置超时。
【问题讨论】:
-
不,不是,如果你尝试从不完整的输入流中获取内容编码之类的标头字段,你会得到另一个 IOException,检查 HttpURLConnection 源代码。
标签: java httpurlconnection urlconnection httpsurlconnection