Skip to content

Instantly share code, notes, and snippets.

@fahied
Forked from kevindelord/etag
Created May 28, 2017 08:01
Show Gist options
  • Save fahied/b3938a02bdd47884480cbe2f8073cb4f to your computer and use it in GitHub Desktop.
Save fahied/b3938a02bdd47884480cbe2f8073cb4f to your computer and use it in GitHub Desktop.
How to integrate Etag in Swift
let API_HEADER_FIELD_NONE_MATCH : String = "If-None-Match"
let API_HEADER_FIELD_ETAG : String = "Etag"
let API_REQUEST_SUCCESS : Int = 200
func ETagForURL(urlString: String) -> String? {
// return the saved ETag value for the given URL
return NSUserDefaults.standardUserDefaults().objectForKey(urlString) as String?
}
func updateETag(urlResponse: NSURLResponse!) {
if let httpResponse = urlResponse as? NSHTTPURLResponse {
if let urlString = httpResponse.URL?.absoluteString {
if let etag = httpResponse.allHeaderFields[API_HEADER_FIELD_ETAG] as? String {
// save the etag header value with the url as a key.
NSUserDefaults.standardUserDefaults().setObject(etag, forKey: urlString)
NSUserDefaults.standardUserDefaults().synchronize()
}
}
}
}
func readFromBackend() {
let urlString = "https://herderbeten.s3.eu-central-1.amazonaws.com/impressum/imprint.html"
// create a mutable request
var request = NSMutableURLRequest(URL: NSURL(string: urlString)!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData, timeoutInterval: 60);
// add etag header value
if let etag = self.ETagForURL(urlString) {
request.addValue(etag, forHTTPHeaderField: API_HEADER_FIELD_NONE_MATCH)
}
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
if (error != nil) {
UIAlertView(title: L("API_ERROR"), message: error.localizedDescription, delegate: nil, cancelButtonTitle: nil, otherButtonTitles:"ok").show()
}
if (response != nil) {
self.updateETag(response)
if let httpResponse = response as? NSHTTPURLResponse {
// Only update the entities if the status code is K_API_REQUEST_SUCCESS (200) and if there is no ERROR
// The status code could also be K_API_REQUEST_CACHED (304) depending on the etag status
if (httpResponse.statusCode == API_REQUEST_SUCCESS && error == nil && data != nil) {
// New data fetched
let htmlText = NSString(data: data, encoding: NSUTF8StringEncoding)
return
}
}
}
// An error occured OR nothing changed. The application should use cached data.
}
}
// MARK: - Write files to cache folder
func writeDataToFile(data: NSData, filename: String) {
if let path = self.getCacheDirectoryFilepath(filename) {
data.writeToFile(path, atomically: false)
self.addSkipBackupAttributeToItemAtURL(NSURL.fileURLWithPath(path as NSString))
}
}
func getCacheDirectoryFilepath(filename: String) -> String? {
let directories : [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
if let cacheFolderPath = directories?.first {
return cacheFolderPath.stringByAppendingPathComponent(filename)
}
return nil
}
func addSkipBackupAttributeToItemAtURL(URL: NSURL!) -> Bool {
assert(NSFileManager.defaultManager().fileExistsAtPath(URL.path!))
var error : NSError? = nil
var success : Bool = URL.setResourceValue(true, forKey: NSURLIsExcludedFromBackupKey, error: &error)
if (success == false || error != nil) {
println("Error excluding \(URL.lastPathComponent) from backup \(error) ")
}
return success
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment