Android HttpResponseCache and "Authorization" request header - android

I'm trying to get HttpResponseCache to cache responses to requests that include an "Authorization" header. I'm including this header because the API I am calling uses basic authentication.
HttpUrlConnection connection = initialiseConnection();
String usernameAndPasswordString = Base64.encodeToString(String.format("%s:%s", username, password).getBytes(), Base64.NO_WRAP);
connection.setRequestProperty("Authorization", String.format("basic %s", usernameAndPasswordString));`
To test this, I'm making the request with WiFi turned on. I'm then turning off WiFi and data and making the request again. I then get a FileNotFoundException when trying to read the response body.
InputStream inputStream = new BufferedInputStream(connection.getInputStream());
If I do the same thing but without the "Authorization" header (to an app on a different server that doesn't use basic auth), my code is able to read the response from the cache.
I am aware that an HTTP cache is not meant to cache a response that was the result of a request including an "Authorization" header, but does that mean that I just can't cache any responses from this server without writing my own cache? Is there any known way around this or to override this behaviour in HttpUrlConnection / HttpResponseCache?
Thanks in advance!

I managed to get to the bottom of this by going through the source code of HttpResponseCache (via https://github.com/candrews/HttpResponseCache, a custom version of the class by candrews taken from the Android source :) ). Including "public", "must-revalidate" or "s-maxage" directives in the Cache-Control header of the response will allow caching by HttpResponseCache even if the Authorization header was included in the request.

Related

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

Difference between okhttp and httpurlconnection?

What are the differences between these 2 libraries?
How I understood there is a difference between these 2 lib also because Volley uses httpurlconnection and Retrofit the okhttp....
But I don't understand the difference between them and pros and cons of both solutions. When is okhttp better and when httpurlconnection?
I would like to know so I know when should I use them.
EDIT:
Why does android use okhttp for the httpurlconnection? before httpurlconnection was not using okhttp if I am not wrong
Pros of okHttp
OkHttp can be customized for every request easily — like timeout customization, etc. for each request.
OkHttp perseveres when the network is troublesome: it will silently recover from common connection problems. If your service has multiple IP addresses OkHttp will attempt alternate addresses if the first connect fails.
Complete analytics of any request can be obtained. You can know bytes sent, bytes received, and the time taken on any request. These analytics are important so that you can find the data usage of your application and the time taken for each request, so you can identify slow requests.
Using OkHttp is easy. Its request/response API is designed with fluent builders and immutability. It supports both synchronous blocking calls and async calls with callbacks.
OkHttp supports Android 2.3 and above. For Java, the minimum requirement is 1.7.
HttpURLConnection
Advantages:
Lightweight APIs help in easier management and reduces compatibility issues.
Automatic handling of the caching mechanisms, with the help of
HttpResponseCache.
Reduces the network usage and also, the battery consumption.
Query Parameter:
URI baseUri = new URI("www.exemple.com/search");
URI uri = applyParameters(baseUri, "word","java");
HttpURLConnection connection =
(HttpURLConnection) uri.toURL().openConnection();
connection.setDoInput(true);
connection.setDoOutput(false);
connection.setRequestMethod("GET");
connection.connect();
if (connection.getResponseCode() ==
HttpURLConnection.HTTP_OK) {
// ...
}
Android Headers Example:
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("CustomHeader", token);
OkHttp
Advantages:
Connection pooling
Gziping
Caching
Recovering from network problems
Redirects
Retries
Support for synchronous and asynchronous calls
Query Parameter:
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://httpbin.org/get").newBuilder();
urlBuilder.addQueryParameter("website", "www.journaldev.com");
urlBuilder.addQueryParameter("tutorials", "android");
String url = urlBuilder.build().toString();
Request request = new Request.Builder()
.url(url)
.build();
Android Headers Example:
Request request = new Request.Builder()
.header("Authorization", "replace this text with your token")
.url("your api url")
.build();
The API's are different, personally I prefer the OkHttp ones.
Note that starting from Android 4.4, the networking layer (so also the HttpUrlConnection APIs) is implemented through OkHttp.

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

Handling Http 304 Response In Android

I am using HttpURLConnection for communication with server and using HttpResponseCache for caching, when server respond with 304 (HTTP_NOT_MODIFIED), i got empty body, but according to documentation of HttpURLConnection and HttpResponseCache, in case 304 HttpUrlConnection will fetch the response for the same URL in the cache. While the request for url is cached and i confirmed it. when url is called first time i get proper response (data) while after cached when i called url, Why i am getting empty body (no data).
I fixed the issue by downloading volley library from official google code repository this is the link
https://android.googlesource.com/platform/frameworks/volley/+/master.
Actually the volley source code available at github is customized and cause many issues (github link: https://github.com/mcxiaoke/android-volley), never download from that link.

Android Compress data for posting to web server

I am still a beginner in Android. I am currently sending large amount of data(json) from the android app to web server using HTTPClient. I found that HttpURLConnection supports decompression for request but is there any support or any way that I can upload a compress/gzipped json to the web server?
Is the only way to achieve this is to manually gzip the json string and put the gzipped string into in to the post?
You can add GZIP compression in your HTTP header.
HttpUriRequest request = new HttpGet(url);
request.addHeader("Content-Encoding", "gzip");
// ...
httpClient.execute(request);
You can check this link for more information

Categories

Resources