mirror of
https://github.com/swisspol/GCDWebServer.git
synced 2026-05-31 00:00:10 +08:00
Added GCDWebServerChunkedResponse
This commit is contained in:
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
typedef NSData* (^GCDWebServerChunkBlock)();
|
||||||
|
|
||||||
@interface GCDWebServerResponse : NSObject
|
@interface GCDWebServerResponse : NSObject
|
||||||
@property(nonatomic, copy) NSString* contentType; // Default is nil i.e. no body
|
@property(nonatomic, copy) NSString* contentType; // Default is nil i.e. no body
|
||||||
@property(nonatomic) NSUInteger contentLength; // Default is NSNotFound i.e. undefined
|
@property(nonatomic) NSUInteger contentLength; // Default is NSNotFound i.e. undefined
|
||||||
@@ -80,3 +82,8 @@
|
|||||||
- (id)initWithFile:(NSString*)path byteRange:(NSRange)range; // Pass [NSNotFound, 0] to disable byte range entirely, [offset, length] to enable byte range from beginning of file or [NSNotFound, -bytes] from end of file
|
- (id)initWithFile:(NSString*)path byteRange:(NSRange)range; // Pass [NSNotFound, 0] to disable byte range entirely, [offset, length] to enable byte range from beginning of file or [NSNotFound, -bytes] from end of file
|
||||||
- (id)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment;
|
- (id)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface GCDWebServerChunkedResponse : GCDWebServerResponse // Use chunked transfer encoding
|
||||||
|
+ (GCDWebServerChunkedResponse*)responseWithContentType:(NSString*)type chunkBlock:(GCDWebServerChunkBlock)block;
|
||||||
|
- (id)initWithContentType:(NSString*)type chunkBlock:(GCDWebServerChunkBlock)block; // Return nil when done
|
||||||
|
@end
|
||||||
|
|||||||
@@ -55,6 +55,15 @@
|
|||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface GCDWebServerChunkedResponse () {
|
||||||
|
@private
|
||||||
|
GCDWebServerChunkBlock _block;
|
||||||
|
NSData* _chunk;
|
||||||
|
NSUInteger _offset;
|
||||||
|
BOOL _terminated;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation GCDWebServerResponse
|
@implementation GCDWebServerResponse
|
||||||
|
|
||||||
@synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, additionalHeaders=_headers;
|
@synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, additionalHeaders=_headers;
|
||||||
@@ -378,3 +387,74 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation GCDWebServerChunkedResponse
|
||||||
|
|
||||||
|
+ (GCDWebServerChunkedResponse*)responseWithContentType:(NSString*)type chunkBlock:(GCDWebServerChunkBlock)block {
|
||||||
|
return ARC_AUTORELEASE([[[self class] alloc] initWithContentType:type chunkBlock:block]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithContentType:(NSString*)type chunkBlock:(GCDWebServerChunkBlock)block {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_block = [block copy];
|
||||||
|
|
||||||
|
self.contentType = type;
|
||||||
|
[self setValue:@"chunked" forAdditionalHeader:@"Transfer-Encoding"];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)open {
|
||||||
|
DCHECK(_chunk == nil);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSInteger)read:(void*)buffer maxLength:(NSUInteger)length {
|
||||||
|
if (_offset >= _chunk.length) {
|
||||||
|
ARC_RELEASE(_chunk);
|
||||||
|
_chunk = nil;
|
||||||
|
}
|
||||||
|
if (_chunk == nil) {
|
||||||
|
if (_terminated) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
NSData* data = _block();
|
||||||
|
if (data.length > 0) {
|
||||||
|
const char* hexString = [[NSString stringWithFormat:@"%lx", (unsigned long)data.length] UTF8String];
|
||||||
|
size_t hexLength = strlen(hexString);
|
||||||
|
_chunk = [[NSMutableData alloc] initWithLength:(hexLength + 2 + data.length + 2)];
|
||||||
|
char* ptr = (char*)_chunk.bytes;
|
||||||
|
bcopy(hexString, ptr, hexLength);
|
||||||
|
ptr += hexLength;
|
||||||
|
*ptr++ = '\r';
|
||||||
|
*ptr++ = '\n';
|
||||||
|
bcopy(data.bytes, ptr, data.length);
|
||||||
|
ptr += data.length;
|
||||||
|
*ptr++ = '\r';
|
||||||
|
*ptr = '\n';
|
||||||
|
} else {
|
||||||
|
_chunk = [[NSData alloc] initWithBytes:"0\r\n\r\n" length:5];
|
||||||
|
_terminated = YES;
|
||||||
|
}
|
||||||
|
_offset = 0;
|
||||||
|
}
|
||||||
|
NSInteger size = MIN(_chunk.length - _offset, length);
|
||||||
|
bcopy((char*)_chunk.bytes + _offset, buffer, size);
|
||||||
|
_offset += size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)close {
|
||||||
|
ARC_RELEASE(_chunk);
|
||||||
|
_chunk = nil;
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
DCHECK(_chunk == nil);
|
||||||
|
ARC_RELEASE(_chunk);
|
||||||
|
|
||||||
|
ARC_DEALLOC(super);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|||||||
Reference in New Issue
Block a user