Can an app setup with HTTP requests, receive json sent via HTTPS? - android

I've had a prototype native Android app sitting on my phone for ages, and use it to demo something to people; it's worked 100's times. The app grabs data from a JSON file on a public server and renders it on a map, nothing special.
Now I have an issue, the data isn't loading anymore!
The server is still running, and I can access the JSON file directly in a web browser, it works fine.
All else is the same except recently I re-configured the server to forward all HTTP traffic to HTTPS, using htaccess rules. This was for another project on the server and same domain.
Would this be the likely culprit? Will an Android app, with hardcoded requests to HTTP urls, have problems it's sent a response as HTTPS ?
I would have traced this on my own... however... I LOST THE SOURCE CODE for the app... something I realized months ago and knew some day it would be a problem.
This is the particular htaccess rule that forwards all HTTP traffic to HTTPS.
Can an exception be made for a particular .json file in the root (mywebsite.com/data.json)?
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.mywebsite.com/$1 [R,L]

Can you try to make another android application for testing and try to load the JSON using HTTP protocol and if that fails, using HTTPS protocol. Also yes, forcing all http -> https may cause issues (although it may seem normal in web browser) . If HTTP fails, just replace all HTTPURLConnection with HTTPSURLConeection and print the String result.
try {
String result = "";
URL url = new URL(YOUR_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream inputStream = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
int i = reader.read();
while(i != -1){
result += (char) i;
i = reader.read();
}
} catch (Exception e) {
e.printStackTrace();
}

Found the answer...
The http-to-https forwarding was the culprit.
I put an exception for my app's data.json (to keep it as HTTP), now the Android app works as usual.
RewriteCond %{SERVER_PORT} 80
RewriteCond %{THE_REQUEST} !/data.json [NC]
RewriteRule ^(.*)$ https://www.mywebsite.com/$1 [R,L]

Related

How to get Android HttpURLConnection to handle a redirect

I'm making an app that basically downloads an image from the URL that I define and save it to the user's device. I'm doing this with:
URL url = new URL("http://speedtest.clotheslinedigital.com");
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.connect();
And then after checking that the storage is working properly and creating a blank file to save onto the device, I use a file output stream and an input stream to download the file to the device.
For testing purposes, I've just been using a Dropbox download link to an image and it's been working perfectly. However, in production, I want to use a DNS subdomain redirect to link to the file, instead of a hardcoded link in my app so that I don't have to update the app if I change the path to the file that the app needs to download.
For testing, I set a 301 redirect through my Godaddy DNS that redirects to the Dropbox link that I was using hardcoded for testing. The subdomain works perfectly when I enter the subdomain on my browser, but when I hardcore the subdomain URL into my app, nothing is downloaded and it just leaves behind a blank file (the one that was made after the request to be used to store the downloaded file).
I've tried using setFollowRedirects() and setting it to true, which I believe is the default but I tried anyway, and it still fails.
I thought maybe the issue was that the HttpURLConnection could not handle 301 response codes from the server, but I looked at the header of the Dropbox link and it 301 redirects the app a couple of times before downloading the file without issues.
Any ideas on how to fix this?
After some more research, it seems that I have to manually handle the redirect in my code. I basically did this by listening to the connection request's response code. If it's a 301 or 302 for a redirect, I have to grab the Location field from the header and feed that through the connection instead.
This is my code to do that:
boolean isRedirect;
do {
if (c.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM || c.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP) {
isRedirect = true;
String newURL = c.getHeaderField("Location");
c = (HttpURLConnection) new URL(newURL).openConnection();
} else {
isRedirect = false;
}
} while (isRedirect);
It's not necessary to encase the whole thing in an kind of loop, but doing so will allow the code to work properly, even if you have multiple redirects that need to be handled.

java.io.IOException: unexpected end of stream on Connection in android

I have web service URL, it working fine. It gives the JSON data.
When I am using HttpURLConnection and InputStream, I am getting this error:
java.io.IOException: unexpected end of stream on
Connection{comenius-api.sabacloud.com:443, proxy=DIRECT
hostAddress=12.130.57.1
cipherSuite=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 protocol=http/1.1}
(recycle count=0)
My code:
try {
URL url = new URL("https://comenius-api.sabacloud.com/v1/people/username=" + username + ":(internalWorkHistory)?type=internal&SabaCertificate=" + certificate);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
InputStream ist = con.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(ist));
while ((singleLine = reader.readLine()) != null) {
data = data + singleLine;
Log.e("Response", data);
}
} catch (Exception e) {
e.printStackTrace();
}
How to fix this?
I had the same problem using OKHttp3. The problem was that I didn't close the connection for each request and for the client the same connection was available and for the server not, for this reason the server returns a error.
The solution is indicating to each request to close the connection when it is finished. You have to add a flag in the header to indicate this. In OKHttp3 is like this:
Request request = new Request.Builder()
.url(URL)
.header("Connection", "close")
...
I encountered this problem today. And it turns out that it is the server fault, as in the server throwed an error and shut down as it is parsing the request.
Check your backend, if it is not yours, notify the owner of that server
"Keepalive makes it difficult for the client to determine where one response ends and the next response begins" 1
It seems that the issue is caused by a collision on reusing alive connection under 2 cases:
server doesn't send Content-Length in response headers
(streaming content case, so no Content-Length can be used) server doesn't use Chunked transfer encoding
So if you observed the exception, sniff http headers (e.g. at Android Studio Profiler tool). If you will see in response header both
"Connection: keep-alive"
and no
"Content-Length: ***" or "Transfer-Encoding: chunked" headers,
then this is the described above case.
Since it is totally server issue, the solution should be to calculate Content-Length and to put it to response header on server side, if it is possible (or to use Chunked transfer encoding).
Recommendation to close connections on the client side should be considered just as a workaround, keep in mind that it degrades overall performance.
Just found out the solution
It is really a server side problem AND The solution is to send the content-length header If you are using php just make your code like this
<?php
ob_start();
// the code - functions .. etc ... example:
$v = print_r($_POST,1);
$v .= "\n\r".print_r($_SERVER,1);
$file = 'file.txt';
file_put_contents($file,$v);
print $v;
// finally
$c = ob_get_contents();
$length = strlen($c);
header('Content-Length: '.$length);
header("Content-Type: text/plain");
//ob_end_flush(); // DID NOT WORK !!
ob_flush()
?>
The trick used here is to send the content-length header using the output buffer
I had the same problem, turned out I still had the proxy configured on the emulator while didn't have Charles open anymore
Consider using OkHttp's retryOnConnectionFailure configuration parameter – as documented, this enables the client to silently recover from:
Stale pooled connections. The ConnectionPool reuses sockets to decrease request latency, but these connections will occasionally time out.
If you happen to be using the ktor client (read: kotlin multiplatform), you can use:
HttpClient(OkHttp) {
engine {
config {
retryOnConnectionFailure(true)
}
}
}
h/t
I was testing my App with localhost using XAMPP and this error was occurring, The problem was with the port i was using skype using 443 port i simply quit skype and error was resolved!
Its a server error. It means somehow execution returns to your client without the server sending actual response header.
If you have control over server code, check that after processing the request, you explicitly send a response header with a response code. That way retrofit knows the request has been processed.
I have the same issue. This error is caused by the server-side only supports http2. You need to update JDK to a version that supports http2 (>=jdk9) to fix this issue.
Add "Connection: keep-alive" to yor Rest Api endpoint
#Headers({"Content-Type: application/json", "Accept: application/json", "Connection: keep-alive"})
This is if your endpoint is being called consecutively
This may be an old thread, as for me, check your internet connection (Wifi) there might be some restriction on accessing some of your endpoints.
I've fixed mine by using/connecting to my mobile data.
-cheers/happy codings
Most probably there are 2 things, happening at the same time.
First, the url contains a port which is not commonly used AND secondly, you are using a VPN or proxy that does not support that port.
Personally, I had the same problem. My server port was 45860 and I was using pSiphon anti-filter VPN.
In that condition my Postman reported "connection hang-up" only when server's relpy was an error with status codes bigger than 0. (it was fine when some text was returning from server with no error code)
Then I changed my web service port to 8080 on my server and, WOW, it worked! although psiphon vpn was connected.Therefore, my suggestion is, if you can change the server port, so try it, or check if there is a proxy problem

Connecting to localhost in Android

I'm developing an App and have designed a bit of Frontend and backend, just the essential. And now, I want to connect both sides. First of all, I need to know how to connect to a localhost in Android.
I tried some tutorials in Internet using for example:
URL url = new URL("http://127.0.0.1");
HttpURLConnection urlConnection = (HttpURLConnection)
url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
} finally {
urlConnection.disconnect();
}
I've tried several approaches but all of them fail. Some doesn't do anything and others stop the App showing some Zygote errors.
My question is clear. How can I connect to localhost in Android? I want a function of the style makeConnectionLocalHost() that returns whether the connection has been successful or not. Any idea why nothing works?
Try instead of using "localhost" your local ip. To retrieve it, open CMD and type ipconfig. There you will find your local ip.
127.0.0.1 will create a loop back to your own device.
You can use InetAddress.getLocalHost() to get localhost address. More details here. And for HttpURLConnection you should have Web-server on this address.

Sending POST request from android to RoR app, but cannot find the right URL

I am not able to reach the create Method in tests_controller.rb with this code.
String newUrl = "http://10.0.2.2:3000/tests";
httpcon = (HttpURLConnection) ((new URL(newUrl).openConnection()));
httpcon.setDoOutput(true);
httpcon.setRequestProperty("Content-Type", "application/json");
httpcon.setRequestProperty("Accept", "application/json");
httpcon.setRequestMethod("POST");
httpcon.connect();
And here is my routes.rb (I use model scaffold to create the RoR app).
resources :tests
Am i wrong in routing or something. When i run this code in Android, the create method is not run at all.
It's hard to tell the reason for the failure you have. Your routes seem OK. You can check couple other things:
Is your Rails server listening on the right interface and port?
Is there any network problem between the machine your client is working on and the server?
Instead of going through the cycle of edit-compile-deploy-run of Android, simply use curl or a similar tool to try the POST request from the console.
When you pinpoint the place of the problem, then you can ask another question, or, more likely, already find the answer online.

Android connect to Mysql database tutorial

Does anybody know a complete and working tutorial about how to retrieve data from MYSQL and display it in Android? I'm asking this because all the tutorials I found are older than API 22 and from API 22 the HttpClient is deprecated. And I'm a new Android Developer so I can't write any code on my own. :)
HttpClient
Interface for an HTTP client. HTTP clients encapsulate a smorgasbord of objects required to execute HTTP requests while handling cookies, authentication, connection management, and other features. Thread safety of HTTP clients depends on the implementation and configuration of the specific client.
This interface was deprecated in API level 22.
Please use openConnection() instead.
Apache HTTP client has fewer bugs on Eclair and Froyo. It is the best choice for these releases.
For Gingerbread and better, HttpURLConnection is the best choice. Its simple API and small size makes it great fit for Android. Transparent compression and response caching reduce network use, improve speed and save battery. New applications should use HttpURLConnection; it is where we will be spending our energy going forward.
Please visit this webpage for further details.
http://android-developers.blogspot.in/2011/09/androids-http-clients.html
An URLConnection for HTTP (RFC 2616) used to send and receive data over the web. Data may be of any type and length. This class may be used to send and receive streaming data whose length is not known in advance.
Uses of this class follow a pattern:
Obtain a new HttpURLConnection by calling URL.openConnection() and casting the result to HttpURLConnection.
Read the response. Response headers typically include metadata such as the response body's content type and length, modified dates and session cookies. The response body may be read from the stream returned by getInputStream(). If the response has no body, that method returns an empty stream.
For example, to retrieve the webpage at http://www.android.com/:
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
}
Please visit this webpage for further details.
http://developer.android.com/reference/java/net/HttpURLConnection.html
urlconnection tutorials, can visit this websites
+http://www.vogella.com/tutorials/AndroidNetworking/article.html
+http://javatechig.com/android/android-networking-tutorial

Categories

Resources