Android HttpURLConnection接收HTTP 301响应代码

时间:2016-10-04 06:49:28

标签: java android json laravel http-status-code-301

我正在尝试使用Android中的HttpURLConnection对象进行HTTP GET。

更新

我尝试连接到其他服务器。它也托管在Cloud 9(c9.io)中,并返回json响应。这次我获得301重定向,但我得到了服务器应该发送的实际响应。

由于这意味着问题已在服务器中进行了本地化,因此我重新组织了以下部分,以便将阅读重点放在与服务器相关的信息上。 Android相关信息已移至问题的最后。

我在哪里连接:

  • Cloud9上的开发服务器
  • 使用Laravel Framework 5.2(由于项目依赖性不受支持,我们目前无法升级到5.3)
  • 服务器应返回JSON答案
  • 如果我通过浏览器连接到同一个网址,我会收到正确的回复(JSON字符串。必需的HTTP标头和'200'HTTP响应代码)

我在哪里连接

  • Android手机(Oneplus 3,在Android 6.0上)
  • 编译SDK版本:23
  • 使用构建工具:“23.0.3”
  • 使用Min SDK verion:19
  • 使用Target SDK版本:22
  • 我使用HttpURLConnection对象连接,使用HTTP方法'GET'

Android上的HTTP响应

当我运行我的代码时,我从服务器获得了后续结果:

HTTP响应代码为301,但邮件为null

  1. 新网址完全相同,但使用的是HTTPS。似乎服务器以某种方式强制SSL / TSL加密。从浏览器访问HTTP时,会发生什么。
  2. HTTP标头(在Android上):

    • date =>星期二,2016年10月4日05:56:26 GMT
    • location => https://domain.com/route/(我修改了这一点)
    • content-length => 382
    • content-type =>为text / html;字符集= ISO-8859-1
    • X-BACKEND =>应用代理
    • X-Android-Selected-Protocol => HTTP / 1.1
    • X-Android-Sent-Millis => 1475560583894
    • X-Android-Received-Millis => 1475560585637
    • X-Android-Response-Source => NETWORK 301
    • null => HTTP / 1.1 301

    其他数据

    1. 由于服务器似乎希望Android使用HTTPS,我尝试修改代码以使用HTTPS(HttpsURLConnection)。这可能会或可能不会解决问题,但我无法检查它,因为我遇到了恼人的SSL handshake failed错误。此外,我不需要对此应用程序进行加密,因此我不愿意解决随之而来的问题。
    2. 这一切都在AsyncTask对象中运行(因为当你尝试在主线程上使用网络连接时,Android会变得情绪化。)
    3. 设置一个新服务器(在Cloud 9之外,没有任何SSL / TSL)可能是一个选项,但我不愿意这样做,因为它会非常耗时。
    4. 我尝试使用完全相同的代码连接到另一台Cloud 9服务器(也返回json响应),一切正常。这表明问题源自HTPP 301错误。
    5. 我将尝试与您分享您回答我的问题所需的任何其他信息!

      原生Android内容(在UPDATE上移动,见上文)

      响应内容似乎不完整 JSON:

      { 'status':'ERROR'
      

      注意我没有忘记关闭}字符,这就是响应实际包含的内容。这是在工作流程中注入某个未知的(对我来说)。当我捕获HTTP响应时(在我的PC上使用Charles,它被设置为我手机的Wi-Fi连接的代理),它的内容是(如预期的那样)一个简单的HTML,告诉您将(HTPP代码301)重定向到新路由。

      无效的JSON代码(上图)不存在,但有效 HTML是。

      这表明无效的JSON出现在我的代码内部(不在服务器或传输上)。但是我的应用程序上没有生成JSON字符串的代码,更不用说将其注入我正在处理的响应中。

      HttpURLConnection的代码

      this.setURL(ruta); //gets correct url
      HttpURLConnection cxn = (HttpURLConnection) this.getURL().openConnection(); //init
      cxn.setRequestMethod("GET"); //use HTTP GET verb
      cxn.setUseCaches(false); //no cache
      cxn.setRequestProperty("Cache-Control", "no-cache"); //even less cache
      cxn.setDoOutput(false); //only true in POST/PUT requests
      cxn.setRequestProperty("Connection","keep-alive");
      cxn.setRequestProperty("DNT", "1"); //TEMP
      cxn.setInstanceFollowRedirects(true); //should follow redirects
      cxn.setRequestProperty( "charset", "utf-8");
      

      阅读结果的代码

      int status_code = cxn.getResponseCode();
      InputStream responseStream = new BufferedInputStream(cxn.getInputStream());
      BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
      String line = "";
      StringBuilder stringBuilder = new StringBuilder();
      while ((line = responseStreamReader.readLine()) != null) {
          stringBuilder.append(line).append("\n");
      }
      responseStreamReader.close();
      String response = stringBuilder.toString();
      cxn.disconnect();
      

4 个答案:

答案 0 :(得分:2)

删除您用于创建HttpURLConnection的代码并尝试使用此代码:

URL url;
HttpURLConnection urlConnection = null;
try {
    url = new URL("http://www.domain.com/index.aspx?parameter1=X&parameter2=X"); //Use your url and add the GET parameters

    urlConnection = (HttpURLConnection) url.openConnection();

    urlConnection.setInstanceFollowRedirects(false); /* added line */

    InputStream in = urlConnection.getInputStream();

    InputStreamReader isw = new InputStreamReader(in);

    int data = isw.read();
    while (data != -1) {
        char current = (char) data;
        data = isw.read();
        System.out.print(current);
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (urlConnection != null) {
        urlConnection.disconnect();
    }    
}

这应该是您为GET请求设置的全部内容。

修改

我使用Volley测试了网络服务,这里是我用来检索网络服务响应的代码:

public class MainActivity extends AppCompatActivity {

  public String response;
  TextView textView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    textView = (TextView) findViewById(R.id.rTextView);

    RequestQueue queue = Volley.newRequestQueue(this);
    String url = "yourWebserviceUrl";

    // Request a string response from the provided URL. 
    StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
      new Response.Listener < String > () {
        @Override
        public void onResponse(String response) {
          textView.setText("Response is: " + response);
        }
      }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
          textView.setText("That didn't work!");
        }
      });
    // Add the request to the RequestQueue. 
    queue.add(stringRequest);

  }

}

这是我得到的回应:

{"status":"ok","found":false,"extra":"App\\Scanners"}

答案 1 :(得分:1)

将协议更改为https对我有用。

答案 2 :(得分:0)

更改行: HttpURLConnection cxn = (HttpURLConnection) this.getURL().openConnection();

与: HttpsURLConnection cxn = (HttpsURLConnection) this.getURL().openConnection();

因此您将能够处理https

答案 3 :(得分:0)

我遇到了同样的问题,在阅读了this source之后,我将其修复。
我们需要做的就是处理如下所示的3 **个错误

if(responseCode > 300 && responseCode < 400) {

    String redirectHeader = conn.getHeaderField("Location");
    if(TextUtils.isEmpty(redirectHeader)) {                       
        return new JsonResponse(responseCode, "Failed to redirect");
    }
    JsonRequest newRequest = request;
    newRequest.url = redirectHeader;
    return getJsonFromUrl(newRequest);
}

每个3 **响应应包含一个标题为 Location 的标头,其中包含我们应使用的重定向链接。