I use a web application that's returning a Content-MD5 header but in my iOS app, I cannot retrieve that header using [NSHTTPURLResponse allHeaderFields] (whereas I can see it when I use cURL).
Does anyone know if iOS is deliberately removing that header?
So I've figured out what's happened.
Our SaaS provider has activated gzip by default on non-production instances. As mentioned in some other threads, NSURLConnection supports gzip compression transparently and will automatically send the Accept-Encoding: gzip HTTP header. When the response is received, NSURLConnection decompresses the content and removes the Content-Md5 header (because the Content-MD5 is a hash of the compressed data), which is why I'm not seeing it in the list of received headers.
Related
In my iOS app I want to cache images that are requested from different destinations. For downloading images I use URLSessionDataTasks with the default caching mechanism provided by URLSession.shared, which makes use of the NSURLRequestUseProtocolCachePolicy.
The caching works basically fine. Responses are being cached and cache headers like etag and cache-control "max-age" are correctly being handled. But if the server responds with the cache-control header set to "no-cache", the URLCache of the URLSession is still caching the image. I can access the cached response via URLCache.shared.cachedResponse(for: request) and also a new data task with the same request will return time image from the cache (which I validated by using Charles proxy and I'm not seeing the request I am awaiting).
Why isn't it correctly handling the respond's cache header? Do I need to manually check the respond's cache headers?
The no-cache directive doesn't mean "don't store it in the cache". Rather it instructs the cache not to serve a cached response without validating with the server first. The [RFC7234][1] specification says the following regarding the no-cache directive.
The "no-cache" response directive indicates that the response MUST NOT
be used to satisfy a subsequent request without successful validation
on the origin server. This allows an origin server to prevent a cache
from using it to satisfy a request without contacting it, even by
caches that have been configured to send stale responses.
If the no-cache response directive specifies one or more field-names,
then a cache MAY use the response to satisfy a subsequent request,
subject to any other restrictions on caching. However, any header
fields in the response that have the field-name(s) listed MUST NOT be
sent in the response to a subsequent request without successful
revalidation with the origin server. This allows an origin server to
prevent the re-use of certain header fields in a response, while still
allowing caching of the rest of the response.
So what will happen is that for "fresh" responses with the no-cache directive, a conditional request will be sent to verify whether the stored response can be used. If the response is still valid, the server will send a 304 - Not Modified response. Upon receiving the 304 response, the cache will serve the stored response with the no-cache directive. If the stored response is no longer valid, the server will send a new response.
[1]: https://www.rfc-editor.org/rfc/rfc7234#section-5.2.2
Does anyone know how to get the gzip version of a response from YQL?
For example requesting this:
http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22AAPL%22)&env=store://datatables.org/alltableswithkeys
The response is not gzipped?
You need to set the header "Content-Encoding: gzip" in your request.
However if the server doesn't supports gzip compression method you might not get the same response.
The web server is by no means obliged to use any compression method – this depends on the internal settings of the web server and also may depend on the internal architecture of the website in question.
The app I'm currently working on needs to present a notification to the user only when a networking request returns a non-cached response.
The app uses Alamofire for networking requests.
How can I determine if a response from Alamofire came from the cache or not?
the only way is to check HTTP header fields in HTTP response. Cache-Control field tells all caching mechanisms from server to client whether they may cache this object. It is measured in seconds. Cache-Control: max-age=3600 means that the content of respond can be one hour old.
if you need non cached respond from server, you have to specify Cache-Control field in your request as Cache-Control: no-cache
there is no difference if you are using Alamofire or not
I send JSON response via AFNetworking from server to my app request. Also it's one script on server (php) and one DB (MySQL).
When I make requests to different tables (within the same DB) - comes valid response (JSON), but from only one table comes "image/jpeg" (afnetworking says me that) ... although the content-type on the server is correctly configured (header('Content-Type: application/json; charset=utf-8'); in .php).
What could be the problem?
Applied to a support - said they sent the correct headers (JSON)...why then AFNetworking sees the header image/jpeg?
ADDED SCREENSHOT OF CHROME DEV TOOL (correct json here):
But AFNetworking says:
I'm getting data from backend using AFNetworking and set request's cachePolicy as NSURLRequestUseProtocolCachePolicy.
The response headers contain ETag value and Transfer-Encoding is chunked.
In the second time I call the same API, it gets the fresh data instead of getting from cache as expected.
I notice that if the response is not chunked (contain Content-Length header), caching work perfectly
My question is: is it possible to cache chunked response in iOS?
Thank you for any advice
NSURLCache, which AFNetworking uses for caching, doesn't support caching this type of request.
You could try:
using SDURLCache, an open-source alternative that gives you more control, or
subclassing NSURLCache yourself to roll your own implementation
using requests that have supported caching headers