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"];
- for (NSString* file in enumerator) {
- if (![file hasPrefix:@"."]) {
- NSString* type = [[enumerator fileAttributes] objectForKey:NSFileType];
- NSString* escapedFile = [file stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- DCHECK(escapedFile);
- if ([type isEqualToString:NSFileTypeRegular]) {
- [html appendFormat:@"- %@
\n", escapedFile, file];
- } else if ([type isEqualToString:NSFileTypeDirectory]) {
- [html appendFormat:@"- %@/
\n", escapedFile, file];
- }
- }
- [enumerator skipDescendents];
- }
- [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"];
+ for (NSString* file in enumerator) {
+ if (![file hasPrefix:@"."]) {
+ NSString* type = [[enumerator fileAttributes] objectForKey:NSFileType];
+ NSString* escapedFile = [file stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+ DCHECK(escapedFile);
+ if ([type isEqualToString:NSFileTypeRegular]) {
+ [html appendFormat:@"- %@
\n", escapedFile, file];
+ } else if ([type isEqualToString:NSFileTypeDirectory]) {
+ [html appendFormat:@"- %@/
\n", escapedFile, file];
+ }
+ }
+ [enumerator skipDescendents];
+ }
+ [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"