que poner etiqueta ejemplos cursiva como ios http-headers nsurlsession nsurlcache nshttpurlresponse

ios - poner - tags h1 y cursiva en word



¿Cómo usar NSURLSession para determinar si el recurso ha cambiado? (2)

Estoy usando NSURLSession para solicitar un recurso JSON de un servidor HTTP. El servidor utiliza Cache-Control para limitar el tiempo de almacenamiento en caché del recurso en los clientes.

Esto funciona muy bien, pero también me gustaría almacenar en caché un objeto JSON deserializado en la memoria, ya que se accede con bastante frecuencia, mientras continúo aprovechando los mecanismos de almacenamiento en caché HTTP integrados en NSURLSession.

Creo que puedo guardar algunos encabezados de respuesta HTTP: Content-MD5 , Etag y Last-Modified junto con el objeto JSON deserializado (estoy usando esos 3 campos ya que noté que no todos los servidores HTTP devuelven Content-MD5 De lo contrario, sería suficiente por sí mismo). La próxima vez que reciba una respuesta para el objeto JSON, si esos 3 campos son iguales, entonces puedo reutilizar el objeto JSON previamente deserializado.

¿Es esta una forma robusta de determinar que el JSON deserizonado sigue siendo válido? Si no, ¿cómo puedo determinar si el objeto deserializado está actualizado?


Creé una estructura HTTPEntityFingerprint que almacena algunos de los encabezados de las entidades: Content-MD5 , Etag y Last-Modified .

import Foundation struct HTTPEntityFingerprint { let contentMD5 : String? let etag : String? let lastModified : String? } extension HTTPEntityFingerprint { init?(response : NSURLResponse) { if let httpResponse = response as? NSHTTPURLResponse { let h = httpResponse.allHeaderFields contentMD5 = h["Content-MD5"] as? String etag = h["Etag"] as? String lastModified = h["Last-Modified"] as? String if contentMD5 == nil && etag == nil && lastModified == nil { return nil } } else { return nil } } static func match(first : HTTPEntityFingerprint?, second : HTTPEntityFingerprint?) -> Bool { if let a = first, b = second { if let md5A = a.contentMD5, md5B = b.contentMD5 { return md5A == md5B } if let etagA = a.etag, etagB = b.etag { return etagA == etagB } if let lastA = a.lastModified, lastB = b.lastModified { return lastA == lastB } } return false } }

Cuando obtengo una NSHTTPURLResponse desde una NSURLSession , creo una HTTPEntityFingerprint y la comparo con una huella digital previamente almacenada utilizando HTTPEntityFingerprint.match . Si las huellas dactilares coinciden, entonces el recurso HTTP no ha cambiado y, por lo tanto, no necesito deserializar la respuesta JSON nuevamente; sin embargo, si las huellas dactilares no coinciden, deserializo la respuesta JSON y guardo la nueva huella digital.

Este mecanismo solo funciona si su servidor devuelve al menos uno de los 3 encabezados de entidad: Content-MD5 , Etag o Last-Modified .

Más detalles sobre NSURLSession y NSURLCache Behavior

El almacenamiento en caché proporcionado por NSURLSession través de NSURLCache es transparente, lo que significa que cuando solicite un recurso previamente almacenado en caché, NSURLSession llamará a los controladores / delegados de finalización como si se hubiera producido una respuesta 200.

Si la respuesta en caché ha expirado, NSURLSession enviará una nueva solicitud al servidor de origen, pero incluirá los encabezados If-Modified-Since y If-None-Match utilizando los encabezados de las entidades Last-Modified y Etag en la Etag caché (aunque caducados) resultado; este comportamiento está integrado, no tiene que hacer nada además de habilitar el almacenamiento en caché. Si el servidor de origen devuelve un 304 (No modificado), NSURLSession lo transformará en una respuesta 200 de la aplicación (haciendo que parezca que ha obtenido una nueva copia del recurso, aunque todavía se haya servido desde la memoria caché).


Esto podría hacerse con una respuesta estándar HTTP simple.

Supongamos que la respuesta anterior es algo como a continuación:

{ status code: 200, headers { "Accept-Ranges" = bytes; Connection = "Keep-Alive"; "Content-Length" = 47616; Date = "Thu, 23 Jul 2015 10:47:56 GMT"; "Keep-Alive" = "timeout=5, max=100"; "Last-Modified" = "Tue, 07 Jul 2015 11:28:46 GMT"; Server = Apache; } }

Ahora use debajo para decirle al servidor que no envíe la fecha si no se modifica desde entonces.

NSURLSession es un contenedor configurable, es probable que necesites usar la opción http "IF-Modified-Since"

Use el tipo de configuración siguiente antes de descargar el recurso,

NSURLSessionConfiguration *backgroundConfigurationObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"myBackgroundSessionIdentifier"]; [backgroundConfigurationObject setHTTPAdditionalHeaders: @{@"If-Modified-Since": @"Tue, 07 Jul 2015 11:28:46 GMT"}];

si el recurso, por ejemplo, no cambia desde la fecha anterior configurada, se llamará a continuación al delegado

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) downloadTask.response; if([httpResponse statusCode] == 304) //resource is not modified since last download date }

Compruebe que el código de estado downloadTask.response es 304 ... entonces el recurso no se modifica y el recurso no se descarga.

Nota: guarde la fecha de descarga completa de éxito anterior en algunos NSUserDefaults para establecerla en if-modifed-since