Added support for "ETag" and "If-None-Match" headers

This commit is contained in:
Pierre-Olivier Latour
2014-04-08 23:25:33 -07:00
parent c454dc4e8e
commit 6210564bfc
6 changed files with 18 additions and 7 deletions
+3
View File
@@ -411,6 +411,9 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
if (_response.lastModifiedDate) { if (_response.lastModifiedDate) {
CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Last-Modified"), (ARC_BRIDGE CFStringRef)GCDWebServerFormatHTTPDate(_response.lastModifiedDate)); CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Last-Modified"), (ARC_BRIDGE CFStringRef)GCDWebServerFormatHTTPDate(_response.lastModifiedDate));
} }
if (_response.eTag) {
CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("ETag"), (ARC_BRIDGE CFStringRef)_response.eTag);
}
if (_response.cacheControlMaxAge > 0) { if (_response.cacheControlMaxAge > 0) {
CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), (ARC_BRIDGE CFStringRef)[NSString stringWithFormat:@"max-age=%i, public", (int)_response.cacheControlMaxAge]); CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), (ARC_BRIDGE CFStringRef)[NSString stringWithFormat:@"max-age=%i, public", (int)_response.cacheControlMaxAge]);
} else { } else {
+1
View File
@@ -126,6 +126,7 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
self.contentType = GCDWebServerGetMimeTypeForExtension([path pathExtension]); self.contentType = GCDWebServerGetMimeTypeForExtension([path pathExtension]);
self.contentLength = (range.location != NSNotFound ? range.length : (NSUInteger)info.st_size); self.contentLength = (range.location != NSNotFound ? range.length : (NSUInteger)info.st_size);
self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec); self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec);
self.eTag = [NSString stringWithFormat:@"%llu/%li/%li", info.st_ino, info.st_mtimespec.tv_sec, info.st_mtimespec.tv_nsec];
} }
return self; return self;
} }
+2 -1
View File
@@ -41,7 +41,8 @@
@property(nonatomic, readonly) NSDictionary* query; // May be nil @property(nonatomic, readonly) NSDictionary* query; // May be nil
@property(nonatomic, readonly) NSString* contentType; // Automatically parsed from headers (nil if request has no body or set to "application/octet-stream" if a body is present without a "Content-Type" header) @property(nonatomic, readonly) NSString* contentType; // Automatically parsed from headers (nil if request has no body or set to "application/octet-stream" if a body is present without a "Content-Type" header)
@property(nonatomic, readonly) NSUInteger contentLength; // Automatically parsed from headers (NSNotFound if request has no "Content-Length" header) @property(nonatomic, readonly) NSUInteger contentLength; // Automatically parsed from headers (NSNotFound if request has no "Content-Length" header)
@property(nonatomic, readonly) NSDate* ifModifiedSinceDate; // Automatically parsed from headers (nil if request has no "If-Modified-Since" header or it is malformatted) @property(nonatomic, readonly) NSDate* ifModifiedSince; // Automatically parsed from headers (nil if request has no "If-Modified-Since" header or it is malformatted)
@property(nonatomic, readonly) NSString* ifNoneMatch; // Automatically parsed from headers (nil if request has no "If-None-Match" header)
@property(nonatomic, readonly) NSRange byteRange; // Automatically parsed from headers ([NSNotFound, 0] if request has no "Range" header, [offset, length] for byte range from beginning or [NSNotFound, -bytes] from end) @property(nonatomic, readonly) NSRange byteRange; // Automatically parsed from headers ([NSNotFound, 0] if request has no "Range" header, [offset, length] for byte range from beginning or [NSNotFound, -bytes] from end)
@property(nonatomic, readonly) BOOL acceptsGzipContentEncoding; @property(nonatomic, readonly) BOOL acceptsGzipContentEncoding;
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query; - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query;
+8 -5
View File
@@ -145,7 +145,8 @@
NSString* _type; NSString* _type;
BOOL _chunked; BOOL _chunked;
NSUInteger _length; NSUInteger _length;
NSDate* _modifiedSinceDate; NSDate* _modifiedSince;
NSString* _noneMatch;
NSRange _range; NSRange _range;
BOOL _gzipAccepted; BOOL _gzipAccepted;
@@ -157,7 +158,7 @@
@implementation GCDWebServerRequest : NSObject @implementation GCDWebServerRequest : NSObject
@synthesize method=_method, URL=_url, headers=_headers, path=_path, query=_query, contentType=_type, contentLength=_length, ifModifiedSinceDate=_modifiedSinceDate, @synthesize method=_method, URL=_url, headers=_headers, path=_path, query=_query, contentType=_type, contentLength=_length, ifModifiedSince=_modifiedSince, ifNoneMatch=_noneMatch,
byteRange=_range, acceptsGzipContentEncoding=_gzipAccepted, usesChunkedTransferEncoding=_chunked; byteRange=_range, acceptsGzipContentEncoding=_gzipAccepted, usesChunkedTransferEncoding=_chunked;
- (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query { - (instancetype)initWithMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers path:(NSString*)path query:(NSDictionary*)query {
@@ -191,10 +192,11 @@
_length = NSNotFound; _length = NSNotFound;
} }
NSString* ifModifiedSinceHeader = [_headers objectForKey:@"If-Modified-Since"]; NSString* modifiedHeader = [_headers objectForKey:@"If-Modified-Since"];
if (ifModifiedSinceHeader) { if (modifiedHeader) {
_modifiedSinceDate = [GCDWebServerParseHTTPDate(ifModifiedSinceHeader) copy]; _modifiedSince = [GCDWebServerParseHTTPDate(modifiedHeader) copy];
} }
_noneMatch = ARC_RETAIN([_headers objectForKey:@"If-None-Match"]);
_range = NSMakeRange(NSNotFound, 0); _range = NSMakeRange(NSNotFound, 0);
NSString* rangeHeader = [[_headers objectForKey:@"Range"] lowercaseString]; NSString* rangeHeader = [[_headers objectForKey:@"Range"] lowercaseString];
@@ -243,6 +245,7 @@
ARC_RELEASE(_query); ARC_RELEASE(_query);
ARC_RELEASE(_type); ARC_RELEASE(_type);
ARC_RELEASE(_modifiedSinceDate); ARC_RELEASE(_modifiedSinceDate);
ARC_RELEASE(_noneMatch);
ARC_RELEASE(_decoders); ARC_RELEASE(_decoders);
ARC_DEALLOC(super); ARC_DEALLOC(super);
+1
View File
@@ -39,6 +39,7 @@
@property(nonatomic) NSInteger statusCode; // Default is 200 @property(nonatomic) NSInteger statusCode; // Default is 200
@property(nonatomic) NSUInteger cacheControlMaxAge; // Default is 0 seconds i.e. "Cache-Control: no-cache" @property(nonatomic) NSUInteger cacheControlMaxAge; // Default is 0 seconds i.e. "Cache-Control: no-cache"
@property(nonatomic, retain) NSDate* lastModifiedDate; // Default is nil i.e. no "Last-Modified" header @property(nonatomic, retain) NSDate* lastModifiedDate; // Default is nil i.e. no "Last-Modified" header
@property(nonatomic, copy) NSString* eTag; // Default is nil i.e. no "ETag" header
@property(nonatomic, getter=isGZipContentEncodingEnabled) BOOL gzipContentEncodingEnabled; // Default is disabled @property(nonatomic, getter=isGZipContentEncodingEnabled) BOOL gzipContentEncodingEnabled; // Default is disabled
+ (instancetype)response; + (instancetype)response;
- (instancetype)init; - (instancetype)init;
+3 -1
View File
@@ -157,6 +157,7 @@
NSInteger _status; NSInteger _status;
NSUInteger _maxAge; NSUInteger _maxAge;
NSDate* _lastModified; NSDate* _lastModified;
NSString* _eTag;
NSMutableDictionary* _headers; NSMutableDictionary* _headers;
BOOL _chunked; BOOL _chunked;
BOOL _gzipped; BOOL _gzipped;
@@ -169,7 +170,7 @@
@implementation GCDWebServerResponse @implementation GCDWebServerResponse
@synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, lastModifiedDate=_lastModified, @synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, lastModifiedDate=_lastModified, eTag=_eTag,
gzipContentEncodingEnabled=_gzipped, additionalHeaders=_headers; gzipContentEncodingEnabled=_gzipped, additionalHeaders=_headers;
+ (instancetype)response { + (instancetype)response {
@@ -191,6 +192,7 @@
- (void)dealloc { - (void)dealloc {
ARC_RELEASE(_type); ARC_RELEASE(_type);
ARC_RELEASE(_lastModified); ARC_RELEASE(_lastModified);
ARC_RELEASE(_eTag);
ARC_RELEASE(_headers); ARC_RELEASE(_headers);
ARC_RELEASE(_encoders); ARC_RELEASE(_encoders);