I'm trying to do a HTTP GET using the HttpURLConnection object in Android.
UPDATE
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 not getting a 301 redirect, but I am getting the actual response the server is supposed to send.
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.
Where I am connecting:
- Development server on Cloud9
- Using the Laravel Framework 5.2 (we cannot upgrade to 5.3 at this time, due to unsupported project dependencies)
- The server should return a JSON answer
- 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)
Where I am connecting FROM
- Android phone (Oneplus 3, on Android 6.0)
- Compile SDK version: 23
- Using Build Tools: "23.0.3"
- Using Min SDK verion: 19
- Using Target SDK version: 22
- I'm connectiong using a HttpURLConnection object, using HTTP Method 'GET'
HTTP Response on Android
When I run my code I get the folling result from the server:
The HTTP response code is 301
but the message is null
.
- The new URL is exactly the same, but using HTTPS. It seems server is somehow forcing SSL/TSL encryption. Which does not happen when accessing HTTP from the browser.
HTTP Header (on Android):
- date => Tue, 04 Oct 2016 05:56:26 GMT
- location => https://domain.com/route/ (I modified this bit)
- content-length => 382
- content-type => text/html; charset=iso-8859-1
- X-BACKEND => apps-proxy
- 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
Other data
- 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 this problem, but I am unable to check it since I get an annoying
SSL handshake failed
error. Plus I have no need for encryption on this application, and therefore I'm reluctant to solve the problems coming with it. - This is all running within an AsyncTask object (since Android get moody when you try to use a network connection on the main thread).
- 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.
- 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.
I will try to share with you any other information you may require to answer my question!
Native Android stuff (moved on UPDATE, see above)
The response content seems to be an incomplete JSON:
{ 'status':'ERROR'
Note I did NOT forget the closing }
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.
The invalid JSON code (above) isn't there, but a valid HTML is.
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.
Code for the 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");
Code for the reading the result
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();