Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm using Alamofire 5 and have the requirement that some GET-requests should be cached. If the data is older then 20 minutes the real API should be hit.

What I found is to use the ResponseCacher. But I do not see a way to configure the individual request and need some advice.

let responseCacher = ResponseCacher(behavior: .modify { _, response in
          let userInfo = ["date": Date()]
          return CachedURLResponse(
            response: response.response,
            data: response.data,
            userInfo: userInfo,
            storagePolicy: .allowed)
        })
let configuration = URLSessionConfiguration.af.default

private override init() {
   configuration.timeoutIntervalForRequest = 10
        configuration.requestCachePolicy = .reloadRevalidatingCacheData
   Session(
      configuration: configuration,
      serverTrustManager: ServerTrustManager(evaluators: evaluators),
      cachedResponseHandler: responseCacher
   )

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
2.6k views
Welcome To Ask or Share your Answers For Others

1 Answer

To elaborate on Jon's answer, the easiest way to achieve what you want is to just let the backend declare the cache semantics of this endpoint, then ensure that on the client side, URLSession uses a URLCache (which is probably the default anyway) and let URLSession and the backend do the rest. This requires, that you have control over the backend, though!

The more elaborate answer:

Here is just an example, how a server may return a response with declared cache semantics:

URL: https://www.example.com/ Status Code: 200
    Age: 238645
    Cache-Control: max-age=604800
    Date: Tue, 12 Jan 2021 18:43:58 GMT
    Etag: "3147526947"
    Expires: Tue, 19 Jan 2021 18:43:58 GMT
    Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
    Vary: Accept-Encoding
    x-cache: HIT

    Accept-Ranges: bytes
    Content-Encoding: gzip
    Content-Length: 648
    Content-Type: text/html; charset=UTF-8
    Server: ECS (dcb/7EC7)

This server literally outputs the full range of what a server can declare regarding caching. The first eight headers (from Age to x-cache) declare the caching.

Cache-Control: max-age=604800 for example declares, that the data's freshness equals 604800 seconds. Having the date when the server created the data, the client can now check if the data is still "fresh".

Expires: Tue, 19 Jan 2021 18:43:58 GMT means the exact same thing, it declares when the data is outdated specifying the wall clock. This is redundant with the above declaration, but it is very clearly defined in the HTTP how clients should treat this.

Having an Age header is a hint, that the response has been actually delivered from a cache that exists between the client and the origin server. The age is the estimation of this data's age - the duration from when it has been created on the origin and when it has been delivered.

I don't wont to go into detail what every header means exactly and how a client and server should behave according HTTP since this is a very intense topic, but what you have to do is basically when you define an endpoint, is just to define the duration of the "freshness" of the returned data.

The whole details: Hypertext Transfer Protocol (HTTP/1.1): Caching

Once you came up with a good duration, Web-application frameworks (like Rails, SpringBoot, etc.) give great help with declaring cache semantics out of the box. Then Web-application frameworks will output the corresponding headers in the response - more or less "automagically".

The URLSession will automatically do the right thing according the HTTP protocol (well, almost). That is, it will store the response in the cache and when you perform a subsequent request it first looks for a suitable response in the cache and return that response if the "freshness" of the data is still given.

If that cached data is too old (according the given response headers and the current data and time), it will try to get a fresh data by sending the request to the origin server. Any upstream cache or eventually the origin server may then return fresh data. Your URLSession data task does all this transparently without giving you a clue whether the data comes from the cache or the origin server. And honestly, in most cases you don't need to know it.

Declaring the cache semantics according HTTP is very powerful and it usually should suit your needs. Also, the client may tailor its needs with specifying certain request headers, for example allowing to return even outdated data or ignoring any cached values, and much more.

Every detail may deserve a dedicated question and answer on SO.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...