diff --git a/GCDWebServer/Responses/GCDWebServerStreamedResponse.h b/GCDWebServer/Responses/GCDWebServerStreamedResponse.h index 4f39625..53b6eba 100644 --- a/GCDWebServer/Responses/GCDWebServerStreamedResponse.h +++ b/GCDWebServer/Responses/GCDWebServerStreamedResponse.h @@ -29,8 +29,8 @@ /** * The GCDWebServerStreamBlock is called to stream the data for the HTTP body. - * The block must return empty NSData when done or nil on error and set the - * "error" argument which is guaranteed to be non-NULL. + * The block must return either a chunk of data, an empty NSData when done, or + * nil on error and set the "error" argument which is guaranteed to be non-NULL. */ typedef NSData* (^GCDWebServerStreamBlock)(NSError** error); @@ -39,13 +39,10 @@ typedef NSData* (^GCDWebServerStreamBlock)(NSError** error); * except the streamed data can be returned at a later time allowing for * truly asynchronous generation of the data. * - * The block must return empty NSData when done or nil on error and set the - * "error" argument which is guaranteed to be non-NULL. + * The block must call "completionBlock" passing the new chunk of data when ready, + * an empty NSData when done, or nil on error and pass a NSError. * - * The block must regularly call "completionBlock" passing new streamed data. - * Eventually it must call "completionBlock" passing an empty NSData indicating - * the end of the stream has been reached, or pass nil and an NSError in case of - * error. + * The block cannot call "completionBlock" more than once per invocation. */ typedef void (^GCDWebServerAsyncStreamBlock)(GCDWebServerBodyReaderCompletionBlock completionBlock); diff --git a/Mac/main.m b/Mac/main.m index 6e35930..c316fde 100644 --- a/Mac/main.m +++ b/Mac/main.m @@ -52,8 +52,7 @@ typedef enum { kMode_WebDAV, kMode_WebUploader, kMode_StreamingResponse, - kMode_AsyncResponse, - kMode_AsyncResponse2 + kMode_AsyncResponse } Mode; @interface Delegate : NSObject @@ -145,7 +144,7 @@ int main(int argc, const char* argv[]) { BOOL bindToLocalhost = NO; if (argc == 1) { - fprintf(stdout, "Usage: %s [-mode webServer | htmlPage | htmlForm | htmlFileUpload | webDAV | webUploader | streamingResponse | asyncResponse | asyncResponse2] [-record] [-root directory] [-tests directory] [-authenticationMethod Basic | Digest] [-authenticationRealm realm] [-authenticationUser user] [-authenticationPassword password] [--localhost]\n\n", basename((char*)argv[0])); + fprintf(stdout, "Usage: %s [-mode webServer | htmlPage | htmlForm | htmlFileUpload | webDAV | webUploader | streamingResponse | asyncResponse] [-record] [-root directory] [-tests directory] [-authenticationMethod Basic | Digest] [-authenticationRealm realm] [-authenticationUser user] [-authenticationPassword password] [--localhost]\n\n", basename((char*)argv[0])); } else { for (int i = 1; i < argc; ++i) { if (argv[i][0] != '-') { @@ -169,8 +168,6 @@ int main(int argc, const char* argv[]) { mode = kMode_StreamingResponse; } else if (!strcmp(argv[i], "asyncResponse")) { mode = kMode_AsyncResponse; - } else if (!strcmp(argv[i], "asyncResponse2")) { - mode = kMode_AsyncResponse2; } } else if (!strcmp(argv[i], "-record")) { recording = YES; @@ -360,7 +357,7 @@ int main(int argc, const char* argv[]) { fprintf(stdout, "Running in Async Response mode"); webServer = [[GCDWebServer alloc] init]; [webServer addHandlerForMethod:@"GET" - path:@"/" + path:@"/async" requestClass:[GCDWebServerRequest class] asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) { @@ -370,15 +367,8 @@ int main(int argc, const char* argv[]) { }); }]; - break; - } - - // Test async responses 2 - case kMode_AsyncResponse2: { - fprintf(stdout, "Running in Async Response 2 mode"); - webServer = [[GCDWebServer alloc] init]; [webServer addHandlerForMethod:@"GET" - path:@"/" + path:@"/async2" requestClass:[GCDWebServerRequest class] asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock handlerCompletionBlock) { diff --git a/README.md b/README.md index 1973128..e065455 100644 --- a/README.md +++ b/README.md @@ -188,22 +188,23 @@ New in GCDWebServer 3.0 is the ability to process HTTP requests aysnchronously i requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { + NSMutableArray* contents = [NSMutableArray arrayWithObjects:@"

\n", @"Hello World!\n", @"

\n", nil]; // Fake data source we are reading from GCDWebServerStreamedResponse* response = [GCDWebServerStreamedResponse responseWithContentType:@"text/html" asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) { + // Simulate a delay reading from the fake data source dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - completionBlock([@"

Hello" dataUsingEncoding:NSUTF8StringEncoding], nil); // Generate the 1st part of the stream data - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - completionBlock([@"World

" dataUsingEncoding:NSUTF8StringEncoding], nil); // Generate the 2nd part of the stream data - + NSString* string = contents.firstObject; + if (string) { + [contents removeObjectAtIndex:0]; + completionBlock([string dataUsingEncoding:NSUTF8StringEncoding], nil); // Generate the 2nd part of the stream data + } else { completionBlock([NSData data], nil); // Must pass an empty NSData to signal the end of the stream - }); - + } }); }]; return response; - + }]; ```