I have an issue using Volley with conditional GETs on cached responses when the request goes through one or more redirect hops.
On the initial request, if the server responds with a 302, the HTTP stack (I'm using the default HurlStack) transparently follows the redirect(s) and ultimately returns the response from the final server.
On subsequent requests, Volley adds an If-Modified-Since header to perform a conditional GET, but these are sent to the initial server, so instead of redirecting we just get a 304 response and the request never reaches the final server.
Since Volley is very loosely coupled with its underlying HTTP stack, there's no way to communicate the fact that the cache headers should only be sent with the final request.
The best solution that I can see (besides never sending conditional GETs) is to write a custom HttpUrlConnection implementation that recognizes that certain headers belong to a specific URL and only sends those headers when appropriate. This means, I would have to save the URL of the final server somewhere, probably as a custom header so that it is saved in the cache along with the other headers.
A slightly less hacky solution would be to write a custom HttpStack implementation that handles redirects manually. But that would mean we could not reuse the connection for redirects to the same host, so it would be less efficient.
Has anyone else run into this issue and have a better solution? It doesn't seem to be specific to Volley or HttpUrlConnection, but to any HTTP library that handles redirects transparently. How do you tell it which headers go with a given URL?
Related
I'm try to do Android offline caching method using OkHttp. The flow is like this:
I send an HTTP request with an ETag empty string at header field if-none-catched to the server, and the server returns a proper ETag.
Then I store the ETag and cache the response.
Next time when I fire the same service call I get the same ETag and set it to the HTTP request header and the server will return HTTP 304 if the ETag is the same.
My issue now is how can I store and retrieve the ETag? Does OkHttp default will handle or I need store at SQLite? I keep looking on Google about OkHttp implement ETag sample code but all I get is just normal caching method. Link I refer:
I'm trying to use Java's HttpURLConnection to do a "conditional get", but I never get a 304 status code
https://github.com/square/okhttp/wiki/Interceptors
Correct way of setting up cache for OkHttp in Android
https://gist.github.com/polbins/1c7f9303d2b7d169a3b1#file-restcontroller-java-L45
so far what I achieved is only cache for 1st time service call, but never get latest data from server anymore. Appreciate if anyone can provide some guidance or found any good example of handle ETag and if-none-catch dynamically for OkHttp to share with. Any clarification feel free to ask.
You just need to enable OkHttp’s response cache. It’ll use the ETag if your webserver returns one.
I am working on an android application in which i want to use caching mechanism for httpurlrequest. I want to cache the response and want to use again for next request.
So, in android how to cache the response and how to use it next time when we do the same request.
Any working example would be great for me.
How to check whether response is from cache or from server?
How to check whether cache is available for the particular request.
PS: there is no any support of cache from server side. i.e sever doesn't send any 'Cache-Control' header field in response.
Thanks,
I am trying to use the built in HTTPResponseCache in my app (making requests via the HTTPURLConnection API) but am having problems trying to get it to cache any responses that were requested with an Authorization header included.
The only way I can get it to cache the response at all is to explicitly put 'public' in the Cache-Control response header on the server (s-maxage might work too, haven't tried, but explicitly putting private results in no caching); but this will mean that any intermediate proxies will cache the response to serve to other clients, which is not what I want.
My understanding is that a user agent cache would cache responses requested with Authorization headers by default or with a private header. It seems like the HTTPResponseCache is acting like a shared cache in how it is interpreting the headers, rather than a user agent cache. Or is my understanding of the caching standards not correct?
Is there any way I can get the cache to act like a user agent HTTP cache?
This in my install code:
public static void setupCache(Context context, long httpCacheSize){
File httpCacheDir = new File(context.getCacheDir(),"http");
HttpResponseCache.install(httpCacheDir, httpCacheSize);
}
Do I need to do something different here? Or perhaps I need to include some user agent information in my requests?
Whilst I found no solution to this specific issue, I worked around my problem by refactoring my HTTP client code to use Volley (http://developer.android.com/training/volley/index.html) rather than HTTPURLConnection. The caching facilities in Volley are implemented separately to HTTPResponseCache and implement handling of cache control headers as expected for a user agent cache.
When I use OkHttp to GET JSON from a URL like this :
Request request = new Request.Builder()
.url(url).build();
I usually get a same response (sometimes I can get a new response).
If I use like this:
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder().noCache().noStore().build())
.url(url).build();
I will get a new response everytime.
I want to know why I get the same reponse by the first method?
Caching in HTTP
HTTP is typically used for distributed information systems, where performance can be improved by the use of response caches. The HTTP/1.1 protocol includes a number of elements intended to make caching work as well as possible. Because these elements are inextricable from other aspects of the protocol, and because they interact with each other, it is useful to describe the basic caching design of HTTP separately from the detailed descriptions of methods, headers, response codes, etc.
Caching would be useless if it did not significantly improve performance. The goal of caching in HTTP/1.1 is to eliminate the need to send requests in many cases, and to eliminate the need to send full responses in many other cases. The former reduces the number of network round-trips required for many operations; we use an "expiration" mechanism for this purpose. The latter reduces network bandwidth requirements.
For more information on this, go through Caching in HTTP. Also for help on coding aspect, go through this documentation on Class Cache.
I've been using HttpURLConnection and it's been working so far, and it handles cookies with two lines but now I need to call a http delete request and it needs parameters and the server gets them form the body.
Apparently you can't send a delete method with a body, so I'm not sure if there's a workaround or if I have to abandon HttpURLConnection and use something else for the whole app.
Is there a way to use something else for delete while keeping httpURLConnection for the rest of the app, and what's the recommended one. And is it possible to also give it the session made in still giving it the session made in cookiemanager?