diff --git a/CGDWebServer/GCDWebServer.h b/CGDWebServer/GCDWebServer.h index 40a96df..c461225 100644 --- a/CGDWebServer/GCDWebServer.h +++ b/CGDWebServer/GCDWebServer.h @@ -54,7 +54,12 @@ typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(GCDWebServerRequest* r @interface GCDWebServer (Handlers) - (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block; -- (void)addHandlerForBasePath:(NSString*)basePath localPath:(NSString*)localPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests; // Base path is recursive and case-sensitive - (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block; // Path is case-insensitive - (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block; // Regular expression is case-insensitive @end + +@interface GCDWebServer (GETHandlers) +- (void)addGETHandlerForPath:(NSString*)path staticData:(NSData*)staticData contentType:(NSString*)contentType cacheAge:(NSUInteger)cacheAge; // Path is case-insensitive +- (void)addGETHandlerForPath:(NSString*)path filePath:(NSString*)filePath isAttachment:(BOOL)isAttachment cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests; // Path is case-insensitive +- (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests; // Base path is recursive and case-sensitive +@end diff --git a/CGDWebServer/GCDWebServer.m b/CGDWebServer/GCDWebServer.m index e5a6dce..9055c9a 100644 --- a/CGDWebServer/GCDWebServer.m +++ b/CGDWebServer/GCDWebServer.m @@ -361,96 +361,6 @@ static void _NetServiceClientCallBack(CFNetServiceRef service, CFStreamError* er } processBlock:block]; } -- (GCDWebServerResponse*)_responseWithContentsOfFile:(NSString*)path { - return [GCDWebServerFileResponse responseWithFile:path]; -} - -- (GCDWebServerResponse*)_responseWithPartialContentsOfFile:(NSString*)path byteRange:(NSRange)range { - return [GCDWebServerFileResponse responseWithFile:path byteRange:range]; -} - -- (GCDWebServerResponse*)_responseWithContentsOfDirectory:(NSString*)path { - NSDirectoryEnumerator* enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path]; - if (enumerator == nil) { - return nil; - } - NSMutableString* html = [NSMutableString string]; - [html appendString:@"\n"]; - [html appendString:@"\n"]; - [html appendString:@"\n"]; - return [GCDWebServerDataResponse responseWithHTML:html]; -} - -- (void)addHandlerForBasePath:(NSString*)basePath localPath:(NSString*)localPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests { - if ([basePath hasPrefix:@"/"] && [basePath hasSuffix:@"/"]) { -#if __has_feature(objc_arc) - __unsafe_unretained GCDWebServer* server = self; -#else - GCDWebServer* server = self; -#endif - [self addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { - - if (![requestMethod isEqualToString:@"GET"]) { - return nil; - } - if (![urlPath hasPrefix:basePath]) { - return nil; - } - return ARC_AUTORELEASE([[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]); - - } processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { - - GCDWebServerResponse* response = nil; - NSString* filePath = [localPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]]; - BOOL isDirectory; - if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory]) { - if (isDirectory) { - if (indexFilename) { - NSString* indexPath = [filePath stringByAppendingPathComponent:indexFilename]; - if ([[NSFileManager defaultManager] fileExistsAtPath:indexPath isDirectory:&isDirectory] && !isDirectory) { - return [server _responseWithContentsOfFile:indexPath]; - } - } - response = [server _responseWithContentsOfDirectory:filePath]; - } else if (allowRangeRequests) { - NSRange range = request.byteRange; - if ((range.location != NSNotFound) || (range.length > 0)) { - response = [server _responseWithPartialContentsOfFile:filePath byteRange:range]; - } else { - response = [server _responseWithContentsOfFile:filePath]; - } - [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"]; - } else { - response = [server _responseWithContentsOfFile:filePath]; - } - } - if (response) { - response.cacheControlMaxAge = cacheAge; - } else { - response = [GCDWebServerResponse responseWithStatusCode:404]; - } - return response; - - }]; - } else { - DNOT_REACHED(); - } -} - - (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block { if ([path hasPrefix:@"/"] && [aClass isSubclassOfClass:[GCDWebServerRequest class]]) { [self addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { @@ -489,3 +399,113 @@ static void _NetServiceClientCallBack(CFNetServiceRef service, CFStreamError* er } @end + +@implementation GCDWebServer (GETHandlers) + +- (void)addGETHandlerForPath:(NSString*)path staticData:(NSData*)staticData contentType:(NSString*)contentType cacheAge:(NSUInteger)cacheAge { + GCDWebServerResponse* response = [GCDWebServerDataResponse responseWithData:staticData contentType:contentType]; + response.cacheControlMaxAge = cacheAge; + [self addHandlerForMethod:@"GET" path:path requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { + + return response; + + }]; +} + +- (void)addGETHandlerForPath:(NSString*)path filePath:(NSString*)filePath isAttachment:(BOOL)isAttachment cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests { + [self addHandlerForMethod:@"GET" path:path requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { + + GCDWebServerResponse* response = nil; + if (allowRangeRequests) { + response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange isAttachment:isAttachment]; + [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"]; + } else { + response = [GCDWebServerFileResponse responseWithFile:filePath isAttachment:isAttachment]; + } + response.cacheControlMaxAge = cacheAge; + return response; + + }]; +} + +- (GCDWebServerResponse*)_responseWithContentsOfDirectory:(NSString*)path { + NSDirectoryEnumerator* enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path]; + if (enumerator == nil) { + return nil; + } + NSMutableString* html = [NSMutableString string]; + [html appendString:@"\n"]; + [html appendString:@"\n"]; + [html appendString:@"\n"]; + [html appendString:@"\n"]; + return [GCDWebServerDataResponse responseWithHTML:html]; +} + +- (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests { + if ([basePath hasPrefix:@"/"] && [basePath hasSuffix:@"/"]) { +#if __has_feature(objc_arc) + __unsafe_unretained GCDWebServer* server = self; +#else + GCDWebServer* server = self; +#endif + [self addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) { + + if (![requestMethod isEqualToString:@"GET"]) { + return nil; + } + if (![urlPath hasPrefix:basePath]) { + return nil; + } + return ARC_AUTORELEASE([[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]); + + } processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { + + GCDWebServerResponse* response = nil; + NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]]; + BOOL isDirectory; + if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory]) { + if (isDirectory) { + if (indexFilename) { + NSString* indexPath = [filePath stringByAppendingPathComponent:indexFilename]; + if ([[NSFileManager defaultManager] fileExistsAtPath:indexPath isDirectory:&isDirectory] && !isDirectory) { + return [GCDWebServerFileResponse responseWithFile:indexPath]; + } + } + response = [server _responseWithContentsOfDirectory:filePath]; + } else { + if (allowRangeRequests) { + response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange]; + [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"]; + } else { + response = [GCDWebServerFileResponse responseWithFile:filePath]; + } + } + } + if (response) { + response.cacheControlMaxAge = cacheAge; + } else { + response = [GCDWebServerResponse responseWithStatusCode:404]; + } + return response; + + }]; + } else { + DNOT_REACHED(); + } +} + +@end diff --git a/Mac/main.m b/Mac/main.m index 7720fc6..02f3c49 100644 --- a/Mac/main.m +++ b/Mac/main.m @@ -34,11 +34,13 @@ int main(int argc, const char* argv[]) { GCDWebServer* webServer = [[GCDWebServer alloc] init]; switch (mode) { + // Simply serve contents of home directory case 0: { - [webServer addHandlerForBasePath:@"/" localPath:NSHomeDirectory() indexFilename:nil cacheAge:0 allowRangeRequests:YES]; + [webServer addGETHandlerForBasePath:@"/" directoryPath:NSHomeDirectory() indexFilename:nil cacheAge:0 allowRangeRequests:YES]; break; } + // Renders a HTML page case 1: { [webServer addDefaultHandlerForMethod:@"GET" requestClass:[GCDWebServerRequest class] @@ -50,6 +52,7 @@ int main(int argc, const char* argv[]) { break; } + // Implements an HTML form case 2: { [webServer addHandlerForMethod:@"GET" path:@"/" diff --git a/README.md b/README.md index 7e2f527..886c505 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ int main(int argc, const char* argv[]) { @autoreleasepool { GCDWebServer* webServer = [[GCDWebServer alloc] init]; - [webServer addHandlerForBasePath:@"/" localPath:NSHomeDirectory() indexFilename:nil cacheAge:3600 allowRangeRequests:YES]; + [webServer addGETHandlerForBasePath:@"/" directoryPath:NSHomeDirectory() indexFilename:nil cacheAge:3600 allowRangeRequests:YES]; [webServer runWithPort:8080]; [webServer release]; @@ -171,7 +171,7 @@ Assuming you have a website directory in your app containing HTML template files NSString* websitePath = [[NSBundle mainBundle] pathForResource:@"Website" ofType:nil]; // Add a default handler to serve static files (i.e. anything other than HTML files) -[self addHandlerForBasePath:@"/" localPath:websitePath indexFilename:nil cacheAge:3600 allowRangeRequests:YES]; +[self addGETHandlerForBasePath:@"/" directoryPath:websitePath indexFilename:nil cacheAge:3600 allowRangeRequests:YES]; // Add an override handler for all requests to "*.html" URLs to do the special HTML templatization [self addHandlerForMethod:@"GET"