Skip to content

Commit 514c09d

Browse files
committed
Added truly asynchronous support to GCDWebServerStreamedResponse
1 parent c4bf7b1 commit 514c09d

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

GCDWebServer/Responses/GCDWebServerStreamedResponse.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@
3434
*/
3535
typedef NSData* (^GCDWebServerStreamBlock)(NSError** error);
3636

37+
/**
38+
* The GCDWebServerAsyncStreamBlock works like the GCDWebServerStreamBlock
39+
* except the streamed data can be returned at a later time allowing for
40+
* truly asynchronous generation of the data.
41+
*
42+
* The block must return empty NSData when done or nil on error and set the
43+
* "error" argument which is guaranteed to be non-NULL.
44+
*
45+
* The block must eventually call "completionBlock" passing the streamed data
46+
* if any and the error if applicable.
47+
*/
48+
typedef void (^GCDWebServerAsyncStreamBlock)(GCDWebServerBodyReaderCompletionBlock completionBlock);
49+
3750
/**
3851
* The GCDWebServerStreamedResponse subclass of GCDWebServerResponse streams
3952
* the body of the HTTP response using a GCD block.
@@ -46,8 +59,18 @@ typedef NSData* (^GCDWebServerStreamBlock)(NSError** error);
4659
+ (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block;
4760

4861
/**
49-
* This method is the designated initializer for the class.
62+
* Creates a response with async streamed data and a given content type.
63+
*/
64+
+ (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block;
65+
66+
/**
67+
* Initializes a response with streamed data and a given content type.
5068
*/
5169
- (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block;
5270

71+
/**
72+
* This method is the designated initializer for the class.
73+
*/
74+
- (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block;
75+
5376
@end

GCDWebServer/Responses/GCDWebServerStreamedResponse.m

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
@interface GCDWebServerStreamedResponse () {
3131
@private
32-
GCDWebServerStreamBlock _block;
32+
GCDWebServerAsyncStreamBlock _block;
3333
}
3434
@end
3535

@@ -39,7 +39,21 @@ + (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServe
3939
return ARC_AUTORELEASE([[[self class] alloc] initWithContentType:type streamBlock:block]);
4040
}
4141

42+
+ (instancetype)responseWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block {
43+
return ARC_AUTORELEASE([[[self class] alloc] initWithContentType:type asyncStreamBlock:block]);
44+
}
45+
4246
- (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block {
47+
return [self initWithContentType:type asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) {
48+
49+
NSError* error = nil;
50+
NSData* data = block(&error);
51+
completionBlock(data, error);
52+
53+
}];
54+
}
55+
56+
- (instancetype)initWithContentType:(NSString*)type asyncStreamBlock:(GCDWebServerAsyncStreamBlock)block {
4357
if ((self = [super init])) {
4458
_block = [block copy];
4559

@@ -54,8 +68,8 @@ - (void)dealloc {
5468
ARC_DEALLOC(super);
5569
}
5670

57-
- (NSData*)readData:(NSError**)error {
58-
return _block(error);
71+
- (void)asyncReadDataWithCompletion:(GCDWebServerBodyReaderCompletionBlock)block {
72+
_block(block);
5973
}
6074

6175
- (NSString*)description {

Mac/main.m

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ int main(int argc, const char* argv[]) {
311311
fprintf(stdout, "Running in Streaming Response mode");
312312
webServer = [[GCDWebServer alloc] init];
313313
[webServer addHandlerForMethod:@"GET"
314-
path:@"/"
314+
path:@"/sync"
315315
requestClass:[GCDWebServerRequest class]
316316
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
317317

@@ -327,6 +327,24 @@ int main(int argc, const char* argv[]) {
327327

328328
}];
329329

330+
}];
331+
[webServer addHandlerForMethod:@"GET"
332+
path:@"/async"
333+
requestClass:[GCDWebServerRequest class]
334+
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
335+
336+
__block int countDown = 10;
337+
return [GCDWebServerStreamedResponse responseWithContentType:@"text/plain" asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) {
338+
339+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
340+
341+
NSData* data = countDown ? [[NSString stringWithFormat:@"%i\n", countDown--] dataUsingEncoding:NSUTF8StringEncoding] : [NSData data];
342+
completionBlock(data, nil);
343+
344+
});
345+
346+
}];
347+
330348
}];
331349
break;
332350
}

0 commit comments

Comments
 (0)