Search code examples
jsonswifthttpcachingswiftui

Adding HTTP response to cache


I have an object with some text data received from a remote server using a POST request. Each time the page is opened, the application makes a request to the remote server.

How do I do caching?

Here is my code without caching:

import Foundation

struct NewsFeed: Codable {
    var status: String = ""
    var totalResults: Int = 0
    var posts: [PostItem]
}

struct PostItem: Codable {
    var id: Int
    var title: String
    var link: String
    var date: String
    var category: String
    var thumbnail: String
    var excerpt: String
    var content: String
}

class NewsDecoder: ObservableObject {

    @Published var newsFeed: NewsFeed?
    @Published var hasContent: Bool = false

    init() {
        self.getNews()
    }

    func getNews() {
        let urlString = "http://example.com/feed/json_news/all.json"
        let url = URL(string: urlString)

        guard url != nil else {
            return
        }

        let dataTask = URLSession.shared.dataTask(with: url!) { (data, response, error) in
            DispatchQueue.main.async {
                if error == nil && data != nil {
                    let decoder = JSONDecoder()
                    do {
                        self.newsFeed = try decoder.decode(NewsFeed.self, from: data!)
                        self.hasContent = true
                    } catch {
                        print("Error: \(error)")
                    }
                }
            }
        }

        dataTask.resume()
    }

}

Solution

  • Well, within the HTTP protocol layer, you do not explicitly cache the response. If the backend wishes the client to cache the payload from a POST response which you are later be able to fetch with a GET request, the backend would need to setup the response accordingly by specifying a Content-Location response header and an associated cache control header, according to RFC 7231 4.3.3 POST.

    The payload returned has the location specified in the returned URL, and the URL has the same value as the POST's effective request URL. Please read here for more information about this specifically.

    If that has been done by the backend and if you have configured your URLSession to use a URLCache on the client, the URLLoading mechanism would cache the payload under the URL returned in the "Content-Location" response header.

    If you then issue a GET request with the given URL previously returned in the Content-Location response header, the caching mechanism would take effect.

    However, there is no guarantee that POST caching is implemented on the client. When using URLCache it's worth to carefully investigate its behaviour and check if it is working as expected.