diff --git a/CGDWebServer/GCDWebServerConnection.h b/CGDWebServer/GCDWebServerConnection.h index 4eee105..0f139c4 100644 --- a/CGDWebServer/GCDWebServerConnection.h +++ b/CGDWebServer/GCDWebServerConnection.h @@ -44,6 +44,7 @@ - (void)didUpdateBytesRead; // Called from arbitrary thread after @totalBytesRead is updated - Default implementation does nothing - (void)didUpdateBytesWritten; // Called from arbitrary thread after @totalBytesWritten is updated - Default implementation does nothing - (GCDWebServerResponse*)processRequest:(GCDWebServerRequest*)request withBlock:(GCDWebServerProcessBlock)block; // Only called if the request can be processed +- (GCDWebServerResponse*)replaceResponse:(GCDWebServerResponse*)response forRequest:(GCDWebServerRequest*)request; // Default implementation replaces any response matching the "ETag" or "Last-Modified-Date" header of the request by a barebone "Not-Modified" (304) one - (void)abortRequest:(GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode; // If request headers was malformed, "request" will be nil - (void)close; @end diff --git a/CGDWebServer/GCDWebServerConnection.m b/CGDWebServer/GCDWebServerConnection.m index 8fbe90f..703f870 100644 --- a/CGDWebServer/GCDWebServerConnection.m +++ b/CGDWebServer/GCDWebServerConnection.m @@ -392,35 +392,14 @@ 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) { - 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 = [self replaceResponse:response forRequest:_request]; + if (response) { NSError* error = nil; if ([response hasBody] && ![response performOpen:&error]) { LOG_ERROR(@"Failed opening response body for socket %i: %@", _socket, error); @@ -695,6 +674,34 @@ static NSString* _StringFromAddressData(NSData* data) { return response; } +// 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; +} + +- (GCDWebServerResponse*)replaceResponse:(GCDWebServerResponse*)response forRequest:(GCDWebServerRequest*)request { + 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; + GCDWebServerResponse* newResponse = [GCDWebServerResponse responseWithStatusCode:code]; + newResponse.cacheControlMaxAge = response.cacheControlMaxAge; + newResponse.lastModifiedDate = response.lastModifiedDate; + newResponse.eTag = response.eTag; + DCHECK(newResponse); + return newResponse; + } + return response; +} + - (void)abortRequest:(GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode { DCHECK(_responseMessage == NULL); DCHECK((statusCode >= 400) && (statusCode < 600));