diff --git a/CGDWebServer/GCDWebServerConnection.m b/CGDWebServer/GCDWebServerConnection.m index 3cfa5bb..8fbe90f 100644 --- a/CGDWebServer/GCDWebServerConnection.m +++ b/CGDWebServer/GCDWebServerConnection.m @@ -392,17 +392,41 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Date"), (ARC_BRIDGE CFStringRef)GCDWebServerFormatHTTPDate([NSDate date])); } +// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26 +static inline BOOL _CompareResources(NSString* responseETag, NSString* requestETag, NSDate* responseLastModified, NSDate* requestLastModified) { + if ([requestETag isEqualToString:@"*"] && (!responseLastModified || !requestLastModified || ([responseLastModified compare:requestLastModified] != NSOrderedDescending))) { + return YES; + } else { + if ([responseETag isEqualToString:requestETag]) { + return YES; + } + if (responseLastModified && requestLastModified && ([responseLastModified compare:requestLastModified] != NSOrderedDescending)) { + return YES; + } + } + return NO; +} + // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - (void)_processRequest { DCHECK(_responseMessage == NULL); GCDWebServerResponse* response = [self processRequest:_request withBlock:_handler.processBlock]; if (response) { - NSError* error = nil; - if ([response hasBody] && ![response performOpen:&error]) { - LOG_ERROR(@"Failed opening response body for socket %i: %@", _socket, error); + if ((response.statusCode >= 200) && (response.statusCode < 300) && _CompareResources(response.eTag, _request.ifNoneMatch, response.lastModifiedDate, _request.ifModifiedSince)) { + NSInteger code = [_request.method isEqualToString:@"HEAD"] || [_request.method isEqualToString:@"GET"] ? kGCDWebServerHTTPStatusCode_NotModified : kGCDWebServerHTTPStatusCode_PreconditionFailed; + _response = [[GCDWebServerResponse alloc] initWithStatusCode:code]; + _response.cacheControlMaxAge = response.cacheControlMaxAge; + _response.lastModifiedDate = response.lastModifiedDate; + _response.eTag = response.eTag; + DCHECK(_response); } else { - _response = ARC_RETAIN(response); + NSError* error = nil; + if ([response hasBody] && ![response performOpen:&error]) { + LOG_ERROR(@"Failed opening response body for socket %i: %@", _socket, error); + } else { + _response = ARC_RETAIN(response); + } } }