HttpURLConnection响应缺少状态行(ProtocolException)
问题描述:
我目前正在尝试向IIS服务器发出请求(使用HttpURLConnection
),它将使我重定向直到目标目标。HttpURLConnection响应缺少状态行(ProtocolException)
问题:java.net.ProtocolException: Unexpected status line: <html><head><title>Object moved</title></head><body>
这种情况发生时urlConnection.getInputStream()
被称为(或urlConnection.getResponseCode()
,这就要求它)。
我已经看到很多情况下,问题只是一个配置错误的服务器,但在这种情况下,从伪造一个Android用户代理产生预期结果的Chrome请求。
此外,服务器是一个古老的服务器,它从来不是问题的根源,其配置方式与在生产环境中使用的方式相同。
达到另一个重定向网页正常工作(通过https://com.google/
,2个重定向测试),并达到服务器上的非重定向网页没有任何问题。
我一直在寻找两天,并没有取得任何进展。任何帮助,将不胜感激。
当前使用的代码:
StringBuilder builder = new StringBuilder();
HttpsURLConnection urlConnection = null;
try {
URL url = new URL(urlStrings[0]);
urlConnection = (HttpsURLConnection) url.openConnection();
LogHelper.Log(getBaseContext(), "Request on URL :\n\"" + url + "\"");
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10000);
urlConnection.setConnectTimeout(15000);
urlConnection.setRequestProperty("Accept","*/*");
urlConnection.setDoOutput(false);
urlConnection.setDoInput(true);
urlConnection.setInstanceFollowRedirects(true);
urlConnection.setUseCaches(false);
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);
urlConnection.connect();
int status = urlConnection.getResponseCode();
LogHelper.Log(getBaseContext(), "Status code is \"" + status + "\"");
if (!url.equals(urlConnection.getURL())) {
LogHelper.Log(getBaseContext(), "URL after redirection is :\n\"" + urlConnection.getURL() + "\"");
}
switch (status/100) {
case 1:
case 2:
case 3:
InputStream stream = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line).append("\n");
}
reader.close();
break;
case 4:
case 5:
InputStream errorStream = urlConnection.getErrorStream();
BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream));
String errorLine;
while ((errorLine = errorReader.readLine()) != null) {
builder.append(errorLine).append("\n");
}
errorReader.close();
throw new Exception(builder.toString());
default:
throw new Exception("Unknown status code: " + status);
}
} catch (Exception e) {
LogHelper.Log(getBaseContext(), e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return builder.toString();
产生的错误:
java.net.ProtocolException: Unexpected status line: <html><head><title>Object moved</title></head><body>
at com.android.okhttp.internal.http.StatusLine.parse(StatusLine.java:54)
at com.android.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:239)
at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:104)
at com.android.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:1120)
at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:951)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:482)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(
at com.pushmanager.clientmdm.activities.RegistrationView$1$2.doInBackground(
at com.pushmanager.clientmdm.activities.RegistrationView$1$2.doInBackground(
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
答
事实证明,这种行为是因为在URL字符串中的字符\n
引起的。
我不知道okhttp如何管理这个结果,但删除了这个字符后,问题就消失了。
我唯一的想法是服务器发送不正确的HTTP头。捕获TCP网络流并在此处提供将非常有帮助。你需要为你的设备创建根目录,然后使用http://www.androidtcpdump.com/或Shark for Root等应用程序。您还需要将您的https:// url更改为http:// – pelya
@pelya,问题是,在同一设备上从Chrome请求时,标头是否正确。没有其他联系服务器的方式会产生错误。 此外,服务器是固定在https中,因此通过切换到http捕获流量是不可能的(不幸的是)。有没有其他的方式来获取头文件? – Apzx
Chrome不使用HttpURLConnection,因此您的请求将具有不同的HTTP标头,服务器很可能以不同的方式回复。如果你不能捕获日志,你可以尝试在你的代码中用传统的Apache HttpClient替换HttpURLConnection,并且希望bug能够消失。您还需要将'useLibrary'org.apache.http.legacy''添加到'build.gradle'中 – pelya