Browse Source

Added -preflightRequest: and -overrideResponse:forRequest: APIs

Pierre-Olivier Latour 11 years ago
parent
commit
8619799e62

+ 2 - 1
GCDWebServer/Core/GCDWebServerConnection.h

@@ -44,8 +44,9 @@
 - (BOOL)open;  // Return NO to reject connection e.g. after validating local or remote addresses
 - (void)didReadBytes:(const void*)bytes length:(NSUInteger)length;  // Called after data has been read from the connection
 - (void)didWriteBytes:(const void*)bytes length:(NSUInteger)length;  // Called after data has been written to the connection
+- (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request;  // Called before request is processed to return an override response bypassing processing or nil to continue - Default implementation checks authentication if applicable
 - (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
+- (GCDWebServerResponse*)overrideResponse:(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 were malformed, "request" will be nil
 - (void)close;
 @end

+ 32 - 29
GCDWebServer/Core/GCDWebServerConnection.m

@@ -372,20 +372,23 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
   DCHECK(_responseMessage == NULL);
   BOOL hasBody = NO;
   
-  GCDWebServerResponse* response = [self processRequest:_request withBlock:_handler.processBlock];
+  GCDWebServerResponse* response = [self preflightRequest:_request];
+  if (!response) {
+    response = [self processRequest:_request withBlock:_handler.processBlock];
+  }
   if (response) {
-    response = [self replaceResponse:response forRequest:_request];
-    if (response) {
-      if ([response hasBody]) {
-        [response prepareForReading];
-        hasBody = !_virtualHEAD;
-      }
-      NSError* error = nil;
-      if (hasBody && ![response performOpen:&error]) {
-        LOG_ERROR(@"Failed opening response body for socket %i: %@", _socket, error);
-      } else {
-        _response = ARC_RETAIN(response);
-      }
+    response = [self overrideResponse:response forRequest:_request];
+  }
+  if (response) {
+    if ([response hasBody]) {
+      [response prepareForReading];
+      hasBody = !_virtualHEAD;
+    }
+    NSError* error = nil;
+    if (hasBody && ![response performOpen:&error]) {
+      LOG_ERROR(@"Failed opening response body for socket %i: %@", _socket, error);
+    } else {
+      _response = ARC_RETAIN(response);
     }
   }
   
@@ -704,27 +707,27 @@ static NSString* _StringFromAddressData(NSData* data) {
 #endif
 }
 
-- (GCDWebServerResponse*)processRequest:(GCDWebServerRequest*)request withBlock:(GCDWebServerProcessBlock)block {
-  LOG_DEBUG(@"Connection on socket %i processing request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
+- (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request {
+  LOG_DEBUG(@"Connection on socket %i preflighting request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
   GCDWebServerResponse* response = nil;
-  BOOL authorized = YES;
   if (_server.authenticationBasicAccount) {
     NSString* authorizationHeader = [request.headers objectForKey:@"Authorization"];
     if (![authorizationHeader hasPrefix:@"Basic "] || ![[authorizationHeader substringFromIndex:6] isEqualToString:_server.authenticationBasicAccount]) {
-      authorized = NO;
+      response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_Unauthorized];
+      [response setValue:[NSString stringWithFormat:@"Basic realm=\"%@\"", _server.authenticationRealm] forAdditionalHeader:@"WWW-Authenticate"];
     }
   }
-  if (authorized) {
-    @try {
-      response = block(request);
-    }
-    @catch (NSException* exception) {
-      LOG_EXCEPTION(exception);
-    }
-  } else {
-    response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_Unauthorized];
-    [response setValue:[NSString stringWithFormat:@"Basic realm=\"%@\"", _server.authenticationRealm] forAdditionalHeader:@"WWW-Authenticate"];
-    return response;
+  return response;
+}
+
+- (GCDWebServerResponse*)processRequest:(GCDWebServerRequest*)request withBlock:(GCDWebServerProcessBlock)block {
+  LOG_DEBUG(@"Connection on socket %i processing request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
+  GCDWebServerResponse* response = nil;
+  @try {
+    response = block(request);
+  }
+  @catch (NSException* exception) {
+    LOG_EXCEPTION(exception);
   }
   return response;
 }
@@ -744,7 +747,7 @@ static inline BOOL _CompareResources(NSString* responseETag, NSString* requestET
   return NO;
 }
 
-- (GCDWebServerResponse*)replaceResponse:(GCDWebServerResponse*)response forRequest:(GCDWebServerRequest*)request {
+- (GCDWebServerResponse*)overrideResponse:(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];