title: Android HttpURLConnection receives HTTP 301 response code
body: <p>I'm trying to do a HTTP GET using the HttpURLConnection object in Android. </p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I tried connection to a different server. This is also hosted within Cloud 9 (c9.io) and also returns a json response. This time I'm <strong>not</strong> getting a 301 redirect, but I am getting the actual response the server is supposed to send.</p>
  
  <p>Since this means the problem is localised within the server, I've reorganized the following sections in order to focus reading onto the server-related information. Android related information has been moved to the end of the question.</p>
  
  <p><strong>Where I am connecting:</strong></p>
  
  <ul>
  <li>Development server on Cloud9</li>
  <li>Using the Laravel Framework 5.2 (we cannot upgrade to 5.3 at this time, due to unsupported project dependencies)</li>
  <li>The server should return a JSON answer</li>
  <li>If I connect to the same URL through the browser I get the correct response (JSON string. Required HTTP Headers and a '200' HTTP Response Code)</li>
  </ul>
  
  <p><strong>Where I am connecting FROM</strong></p>
  
  <ul>
  <li>Android phone (Oneplus 3, on Android 6.0)</li>
  <li>Compile SDK version: 23</li>
  <li>Using Build Tools: "23.0.3"</li>
  <li>Using Min SDK verion: 19</li>
  <li>Using Target SDK version: 22</li>
  <li>I'm connectiong using a HttpURLConnection object, using HTTP Method 'GET'</li>
  </ul>
  
  <p><strong>HTTP Response on Android</strong></p>
  
  <p>When I run my code I get the folling result from the server:</p>
  
  <p>The HTTP response code is <code>301</code> but the message is <code>null</code>.</p>
  
  <ol>
  <li>The new URL is exactly the same, but using HTTPS. It seems server is somehow forcing SSL/TSL encryption. Which does <strong>not</strong> happen when accessing HTTP from the browser.</li>
  </ol>
  
  <p>HTTP Header (on Android):</p>
  
  <ul>
  <li>date => Tue, 04 Oct 2016 05:56:26 GMT</li>
  <li>location => <a href="https://domain.com/route/" rel="nofollow">https://domain.com/route/</a> (I modified this bit)</li>
  <li>content-length => 382</li>
  <li>content-type => text/html; charset=iso-8859-1</li>
  <li>X-BACKEND => apps-proxy</li>
  <li>X-Android-Selected-Protocol => http/1.1</li>
  <li>X-Android-Sent-Millis => 1475560583894</li>
  <li>X-Android-Received-Millis => 1475560585637</li>
  <li>X-Android-Response-Source => NETWORK 301</li>
  <li>null => HTTP/1.1 301 </li>
  </ul>
  
  <p><strong>Other data</strong></p>
  
  <ol>
  <li>Since it seems the server wants Android to use HTTPS, I tried modifying the code to use HTTPS (HttpsURLConnection). This may or may not solve <em>this</em> problem, but I am unable to check it since I get an annoying <code>SSL handshake failed</code> error. Plus I have no need for encryption on this application, and therefore I'm reluctant to solve the problems coming with it.</li>
  <li>This is all running within an AsyncTask object (since Android get moody when you try to use a network connection on the main thread).</li>
  <li>Setting up a new server (outside of Cloud 9 and without any SSL/TSL) could be an option, but I'm reluctant to do this since it would be quite time consuming.</li>
  <li>I tried connecting to another Cloud 9 server (which also returns a json response), using the exact same code, and everything works correctly. This suggests that the problem arises from the HTPP 301 error.</li>
  </ol>
  
  <p>I will try to share with you any other information you may require to answer my question!</p>
  
  <p><strong>Native Android stuff (moved on UPDATE, see above)</strong></p>
  
  <p>The response content <em>seems</em> to be an <strong>incomplete</strong> JSON:</p>
  
  <pre><code>{ 'status':'ERROR'
  </code></pre>
  
  <p>Note I did NOT forget the closing <code>}</code> character, that's what the response actually containts. This is injected somewhere unknown (to me) during the workflow. When I capture the HTTP response (using Charles on my PC, which is set as a Proxy for my phone's Wi-Fi connection) it's content is (as expected) a simple HTML telling you to redirect (HTPP code 301) to a new route. </p>
  
  <p>The invalid JSON code (above) isn't there, but a <strong>valid</strong> HTML is. </p>
  
  <p>This would suggest that the invalid JSON appears somewhere internally to my code (not on the server, or transport). But there is no code on my app that generates a JSON string, let alone inject it into the response I'm processing.</p>
  
  <p><strong>Code for the HttpURLConnection</strong></p>
  
  <pre class="lang-java prettyprint-override"><code>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");
  </code></pre>
  
  <p><strong>Code for the reading the result</strong></p>
  
  <pre class="lang-java prettyprint-override"><code>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();
  </code></pre>