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) 
+1

我唯一的想法是服务器发送不正确的HTTP头。捕获TCP网络流并在此处提供将非常有帮助。你需要为你的设备创建根目录,然后使用http://www.androidtcpdump.com/或Shark for Root等应用程序。您还需要将您的https:// url更改为http:// – pelya

+0

@pelya,问题是,在同一设备上从Chrome请求时,标头是否正确。没有其他联系服务器的方式会产生错误。 此外,服务器是固定在https中,因此通过切换到http捕获流量是不可能的(不幸的是)。有没有其他的方式来获取头文件? – Apzx

+1

Chrome不使用HttpURLConnection,因此您的请求将具有不同的HTTP标头,服务器很可能以不同的方式回复。如果你不能捕获日志,你可以尝试在你的代码中用传统的Apache HttpClient替换HttpURLConnection,并且希望bug能够消失。您还需要将'useLibrary'org.apache.http.legacy''添加到'build.gradle'中 – pelya

事实证明,这种行为是因为在URL字符串中的字符\n引起的。

我不知道okhttp如何管理这个结果,但删除了这个字符后,问题就消失了。