diff --git a/GCDWebServer/Core/GCDWebServerConnection.h b/GCDWebServer/Core/GCDWebServerConnection.h index 6bdc00c..338c8e2 100644 --- a/GCDWebServer/Core/GCDWebServerConnection.h +++ b/GCDWebServer/Core/GCDWebServerConnection.h @@ -117,6 +117,14 @@ */ - (void)didWriteBytes:(const void*)bytes length:(NSUInteger)length; +/** + * This method is called after the HTTP headers have been received to + * allow replacing the request URL by another one. + * + * The default implementation returns the original URL. + */ +- (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary*)headers; + /** * Assuming a valid HTTP request was received, this method is called before * the request is processed. diff --git a/GCDWebServer/Core/GCDWebServerConnection.m b/GCDWebServer/Core/GCDWebServerConnection.m index 098f707..e80ca75 100644 --- a/GCDWebServer/Core/GCDWebServerConnection.m +++ b/GCDWebServer/Core/GCDWebServerConnection.m @@ -522,11 +522,15 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { requestMethod = @"GET"; _virtualHEAD = YES; } + NSDictionary* requestHeaders = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyAllHeaderFields(_requestMessage)); // Header names are case-insensitive but CFHTTPMessageCopyAllHeaderFields() will standardize the common ones NSURL* requestURL = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestURL(_requestMessage)); + if (requestURL) { + requestURL = [self rewriteRequestURL:requestURL withMethod:requestMethod headers:requestHeaders]; + DCHECK(requestURL); + } NSString* requestPath = requestURL ? GCDWebServerUnescapeURLString(ARC_BRIDGE_RELEASE(CFURLCopyPath((CFURLRef)requestURL))) : nil; // Don't use -[NSURL path] which strips the ending slash NSString* queryString = requestURL ? ARC_BRIDGE_RELEASE(CFURLCopyQueryString((CFURLRef)requestURL, NULL)) : nil; // Don't use -[NSURL query] to make sure query is not unescaped; NSDictionary* requestQuery = queryString ? GCDWebServerParseURLEncodedForm(queryString) : @{}; - NSDictionary* requestHeaders = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyAllHeaderFields(_requestMessage)); // Header names are case-insensitive but CFHTTPMessageCopyAllHeaderFields() will standardize the common ones if (requestMethod && requestURL && requestHeaders && requestPath && requestQuery) { for (_handler in _server.handlers) { _request = ARC_RETAIN(_handler.matchBlock(requestMethod, requestURL, requestHeaders, requestPath, requestQuery)); @@ -713,6 +717,10 @@ static NSString* _StringFromAddressData(NSData* data) { #endif } +- (NSURL*)rewriteRequestURL:(NSURL*)url withMethod:(NSString*)method headers:(NSDictionary*)headers { + return url; +} + // https://tools.ietf.org/html/rfc2617 - (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);