mirror of
https://github.com/swisspol/GCDWebServer.git
synced 2026-04-24 00:00:04 +08:00
#50 Use NSUIntegerMax instead of NSNotFound to indicate undefined length
This commit is contained in:
@@ -937,7 +937,7 @@ static CFHTTPMessageRef _CreateHTTPMessageFromPerformingRequest(NSData* inData,
|
|||||||
while (1) {
|
while (1) {
|
||||||
ssize_t result = read(httpSocket, (char*)outData.mutableBytes + length, outData.length - length);
|
ssize_t result = read(httpSocket, (char*)outData.mutableBytes + length, outData.length - length);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
length = NSNotFound;
|
length = NSUIntegerMax;
|
||||||
break;
|
break;
|
||||||
} else if (result == 0) {
|
} else if (result == 0) {
|
||||||
break;
|
break;
|
||||||
@@ -947,7 +947,7 @@ static CFHTTPMessageRef _CreateHTTPMessageFromPerformingRequest(NSData* inData,
|
|||||||
outData.length = 2 * outData.length;
|
outData.length = 2 * outData.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (length != NSNotFound) {
|
if (length != NSUIntegerMax) {
|
||||||
outData.length = length;
|
outData.length = length;
|
||||||
response = _CreateHTTPMessageFromData(outData, NO);
|
response = _CreateHTTPMessageFromData(outData, NO);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -416,7 +416,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
|||||||
if (_response.contentType != nil) {
|
if (_response.contentType != nil) {
|
||||||
CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Type"), (ARC_BRIDGE CFStringRef)GCDWebServerNormalizeHeaderValue(_response.contentType));
|
CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Type"), (ARC_BRIDGE CFStringRef)GCDWebServerNormalizeHeaderValue(_response.contentType));
|
||||||
}
|
}
|
||||||
if (_response.contentLength != NSNotFound) {
|
if (_response.contentLength != NSUIntegerMax) {
|
||||||
CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Length"), (ARC_BRIDGE CFStringRef)[NSString stringWithFormat:@"%lu", (unsigned long)_response.contentLength]);
|
CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Content-Length"), (ARC_BRIDGE CFStringRef)[NSString stringWithFormat:@"%lu", (unsigned long)_response.contentLength]);
|
||||||
}
|
}
|
||||||
if (_response.usesChunkedTransferEncoding) {
|
if (_response.usesChunkedTransferEncoding) {
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ extern void GCDLogMessage(GCDWebServerLogLevel level, NSString* format, ...) NS_
|
|||||||
#define kGCDWebServerErrorDomain @"GCDWebServerErrorDomain"
|
#define kGCDWebServerErrorDomain @"GCDWebServerErrorDomain"
|
||||||
|
|
||||||
static inline BOOL GCDWebServerIsValidByteRange(NSRange range) {
|
static inline BOOL GCDWebServerIsValidByteRange(NSRange range) {
|
||||||
return ((range.location != NSNotFound) || (range.length > 0));
|
return ((range.location != NSUIntegerMax) || (range.length > 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline NSError* GCDWebServerMakePosixError(int code) {
|
static inline NSError* GCDWebServerMakePosixError(int code) {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
* Returns the content length for the body of the request parsed from the
|
* Returns the content length for the body of the request parsed from the
|
||||||
* "Content-Length" header.
|
* "Content-Length" header.
|
||||||
*
|
*
|
||||||
* This property will be set to "NSNotFound" if the request has no body or
|
* This property will be set to "NSUIntegerMax" if the request has no body or
|
||||||
* if there is a body but no "Content-Length" header, typically because
|
* if there is a body but no "Content-Length" header, typically because
|
||||||
* chunked transfer encoding is used.
|
* chunked transfer encoding is used.
|
||||||
*/
|
*/
|
||||||
@@ -136,9 +136,9 @@
|
|||||||
@property(nonatomic, readonly) NSString* ifNoneMatch;
|
@property(nonatomic, readonly) NSString* ifNoneMatch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the parsed "Range" header or (NSNotFound, 0) if absent or malformed.
|
* Returns the parsed "Range" header or (NSUIntegerMax, 0) if absent or malformed.
|
||||||
* The range will be set to (offset, length) if expressed from the beginning
|
* The range will be set to (offset, length) if expressed from the beginning
|
||||||
* of the entity body, or (NSNotFound, -length) if expressed from its end.
|
* of the entity body, or (NSUIntegerMax, length) if expressed from its end.
|
||||||
*/
|
*/
|
||||||
@property(nonatomic, readonly) NSRange byteRange;
|
@property(nonatomic, readonly) NSRange byteRange;
|
||||||
|
|
||||||
|
|||||||
@@ -187,14 +187,14 @@
|
|||||||
if (_type == nil) {
|
if (_type == nil) {
|
||||||
_type = kGCDWebServerDefaultMimeType;
|
_type = kGCDWebServerDefaultMimeType;
|
||||||
}
|
}
|
||||||
_length = NSNotFound;
|
_length = NSUIntegerMax;
|
||||||
} else {
|
} else {
|
||||||
if (_type) {
|
if (_type) {
|
||||||
DNOT_REACHED();
|
DNOT_REACHED();
|
||||||
ARC_RELEASE(self);
|
ARC_RELEASE(self);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
_length = NSNotFound;
|
_length = NSUIntegerMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* modifiedHeader = [_headers objectForKey:@"If-Modified-Since"];
|
NSString* modifiedHeader = [_headers objectForKey:@"If-Modified-Since"];
|
||||||
@@ -203,7 +203,7 @@
|
|||||||
}
|
}
|
||||||
_noneMatch = ARC_RETAIN([_headers objectForKey:@"If-None-Match"]);
|
_noneMatch = ARC_RETAIN([_headers objectForKey:@"If-None-Match"]);
|
||||||
|
|
||||||
_range = NSMakeRange(NSNotFound, 0);
|
_range = NSMakeRange(NSUIntegerMax, 0);
|
||||||
NSString* rangeHeader = GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Range"]);
|
NSString* rangeHeader = GCDWebServerNormalizeHeaderValue([_headers objectForKey:@"Range"]);
|
||||||
if (rangeHeader) {
|
if (rangeHeader) {
|
||||||
if ([rangeHeader hasPrefix:@"bytes="]) {
|
if ([rangeHeader hasPrefix:@"bytes="]) {
|
||||||
@@ -222,13 +222,13 @@
|
|||||||
_range.location = startValue;
|
_range.location = startValue;
|
||||||
_range.length = NSUIntegerMax;
|
_range.length = NSUIntegerMax;
|
||||||
} else if (endString.length && (endValue > 0)) { // The final 500 bytes: "-500"
|
} else if (endString.length && (endValue > 0)) { // The final 500 bytes: "-500"
|
||||||
_range.location = NSNotFound;
|
_range.location = NSUIntegerMax;
|
||||||
_range.length = endValue;
|
_range.length = endValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((_range.location == NSNotFound) && (_range.length == 0)) { // Ignore "Range" header if syntactically invalid
|
if ((_range.location == NSUIntegerMax) && (_range.length == 0)) { // Ignore "Range" header if syntactically invalid
|
||||||
LOG_WARNING(@"Failed to parse 'Range' header \"%@\" for url: %@", rangeHeader, url);
|
LOG_WARNING(@"Failed to parse 'Range' header \"%@\" for url: %@", rangeHeader, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,12 +87,12 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the content length for the body of the response. If a body is present
|
* Sets the content length for the body of the response. If a body is present
|
||||||
* but this property is set to "NSNotFound", this means the length of the body
|
* but this property is set to "NSUIntegerMax", this means the length of the body
|
||||||
* cannot be known ahead of time. Chunked transfer encoding will be
|
* cannot be known ahead of time. Chunked transfer encoding will be
|
||||||
* automatically enabled by the GCDWebServerConnection to comply with HTTP/1.1
|
* automatically enabled by the GCDWebServerConnection to comply with HTTP/1.1
|
||||||
* specifications.
|
* specifications.
|
||||||
*
|
*
|
||||||
* The default value is "NSNotFound" i.e. the response has no body or its length
|
* The default value is "NSUIntegerMax" i.e. the response has no body or its length
|
||||||
* is undefined.
|
* is undefined.
|
||||||
*/
|
*/
|
||||||
@property(nonatomic) NSUInteger contentLength;
|
@property(nonatomic) NSUInteger contentLength;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
|
|
||||||
- (id)initWithResponse:(GCDWebServerResponse*)response reader:(id<GCDWebServerBodyReader>)reader {
|
- (id)initWithResponse:(GCDWebServerResponse*)response reader:(id<GCDWebServerBodyReader>)reader {
|
||||||
if ((self = [super initWithResponse:response reader:reader])) {
|
if ((self = [super initWithResponse:response reader:reader])) {
|
||||||
response.contentLength = NSNotFound; // Make sure "Content-Length" header is not set since we don't know it
|
response.contentLength = NSUIntegerMax; // Make sure "Content-Length" header is not set since we don't know it
|
||||||
[response setValue:@"gzip" forAdditionalHeader:@"Content-Encoding"];
|
[response setValue:@"gzip" forAdditionalHeader:@"Content-Encoding"];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -180,7 +180,7 @@
|
|||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
_type = nil;
|
_type = nil;
|
||||||
_length = NSNotFound;
|
_length = NSUIntegerMax;
|
||||||
_status = kGCDWebServerHTTPStatusCode_OK;
|
_status = kGCDWebServerHTTPStatusCode_OK;
|
||||||
_maxAge = 0;
|
_maxAge = 0;
|
||||||
_headers = [[NSMutableDictionary alloc] init];
|
_headers = [[NSMutableDictionary alloc] init];
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)usesChunkedTransferEncoding {
|
- (BOOL)usesChunkedTransferEncoding {
|
||||||
return (_type != nil) && (_length == NSNotFound);
|
return (_type != nil) && (_length == NSUIntegerMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)open:(NSError**)error {
|
- (BOOL)open:(NSError**)error {
|
||||||
@@ -259,7 +259,7 @@
|
|||||||
if (_type) {
|
if (_type) {
|
||||||
[description appendFormat:@"\nContent Type = %@", _type];
|
[description appendFormat:@"\nContent Type = %@", _type];
|
||||||
}
|
}
|
||||||
if (_length != NSNotFound) {
|
if (_length != NSUIntegerMax) {
|
||||||
[description appendFormat:@"\nContent Length = %lu", (unsigned long)_length];
|
[description appendFormat:@"\nContent Length = %lu", (unsigned long)_length];
|
||||||
}
|
}
|
||||||
[description appendFormat:@"\nCache Control Max Age = %lu", (unsigned long)_maxAge];
|
[description appendFormat:@"\nCache Control Max Age = %lu", (unsigned long)_maxAge];
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)open:(NSError**)error {
|
- (BOOL)open:(NSError**)error {
|
||||||
if (self.contentLength != NSNotFound) {
|
if (self.contentLength != NSUIntegerMax) {
|
||||||
_data = [[NSMutableData alloc] initWithCapacity:self.contentLength];
|
_data = [[NSMutableData alloc] initWithCapacity:self.contentLength];
|
||||||
} else {
|
} else {
|
||||||
_data = [[NSMutableData alloc] init];
|
_data = [[NSMutableData alloc] init];
|
||||||
|
|||||||
@@ -77,9 +77,9 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a response like -initWithFile: but restricts the file contents
|
* Initializes a response like -initWithFile: but restricts the file contents
|
||||||
* to a specific byte range. This range should be set to (NSNotFound, 0) for
|
* to a specific byte range. This range should be set to (NSUIntegerMax, 0) for
|
||||||
* the full file, (offset, length) if expressed from the beginning of the file,
|
* the full file, (offset, length) if expressed from the beginning of the file,
|
||||||
* or (NSNotFound, -length) if expressed from the end of the file. The "offset"
|
* or (NSUIntegerMax, length) if expressed from the end of the file. The "offset"
|
||||||
* and "length" values will be automatically adjusted to be compatible with the
|
* and "length" values will be automatically adjusted to be compatible with the
|
||||||
* actual size of the file.
|
* actual size of the file.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -59,11 +59,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithFile:(NSString*)path {
|
- (instancetype)initWithFile:(NSString*)path {
|
||||||
return [self initWithFile:path byteRange:NSMakeRange(NSNotFound, 0) isAttachment:NO];
|
return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment {
|
- (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment {
|
||||||
return [self initWithFile:path byteRange:NSMakeRange(NSNotFound, 0) isAttachment:attachment];
|
return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:attachment];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range {
|
- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range {
|
||||||
@@ -81,31 +81,34 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
|
|||||||
ARC_RELEASE(self);
|
ARC_RELEASE(self);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
if (GCDWebServerIsValidByteRange(range)) {
|
NSUInteger fileSize = (NSUInteger)info.st_size;
|
||||||
if (range.location != NSNotFound) {
|
|
||||||
range.location = MIN(range.location, (NSUInteger)info.st_size);
|
BOOL hasByteRange = GCDWebServerIsValidByteRange(range);
|
||||||
range.length = MIN(range.length, (NSUInteger)info.st_size - range.location);
|
if (hasByteRange) {
|
||||||
|
if (range.location != NSUIntegerMax) {
|
||||||
|
range.location = MIN(range.location, fileSize);
|
||||||
|
range.length = MIN(range.length, fileSize - range.location);
|
||||||
} else {
|
} else {
|
||||||
range.length = MIN(range.length, (NSUInteger)info.st_size);
|
range.length = MIN(range.length, fileSize);
|
||||||
range.location = (NSUInteger)info.st_size - range.length;
|
range.location = fileSize - range.length;
|
||||||
}
|
}
|
||||||
if (range.length == 0) {
|
if (range.length == 0) {
|
||||||
ARC_RELEASE(self);
|
ARC_RELEASE(self);
|
||||||
return nil; // TODO: Return 416 status code and "Content-Range: bytes */{file length}" header
|
return nil; // TODO: Return 416 status code and "Content-Range: bytes */{file length}" header
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
range.location = 0;
|
||||||
|
range.length = fileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
_path = [path copy];
|
_path = [path copy];
|
||||||
if (range.location != NSNotFound) {
|
_offset = range.location;
|
||||||
_offset = range.location;
|
_size = range.length;
|
||||||
_size = range.length;
|
if (hasByteRange) {
|
||||||
[self setStatusCode:kGCDWebServerHTTPStatusCode_PartialContent];
|
[self setStatusCode:kGCDWebServerHTTPStatusCode_PartialContent];
|
||||||
[self setValue:[NSString stringWithFormat:@"bytes %i-%i/%i", (int)range.location, (int)(range.location + range.length - 1), (int)info.st_size] forAdditionalHeader:@"Content-Range"];
|
[self setValue:[NSString stringWithFormat:@"bytes %lu-%lu/%lu", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), (unsigned long)fileSize] forAdditionalHeader:@"Content-Range"];
|
||||||
LOG_DEBUG(@"Using content bytes range [%i-%i] for file \"%@\"", (int)range.location, (int)(range.location + range.length - 1), path);
|
LOG_DEBUG(@"Using content bytes range [%lu-%lu] for file \"%@\"", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), path);
|
||||||
} else {
|
|
||||||
_offset = 0;
|
|
||||||
_size = (NSUInteger)info.st_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attachment) {
|
if (attachment) {
|
||||||
@@ -121,8 +124,8 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.contentType = GCDWebServerGetMimeTypeForExtension([path pathExtension]);
|
self.contentType = GCDWebServerGetMimeTypeForExtension([_path pathExtension]);
|
||||||
self.contentLength = (range.location != NSNotFound ? range.length : (NSUInteger)info.st_size);
|
self.contentLength = _size;
|
||||||
self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec);
|
self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec);
|
||||||
self.eTag = [NSString stringWithFormat:@"%llu/%li/%li", info.st_ino, info.st_mtimespec.tv_sec, info.st_mtimespec.tv_nsec];
|
self.eTag = [NSString stringWithFormat:@"%llu/%li/%li", info.st_ino, info.st_mtimespec.tv_sec, info.st_mtimespec.tv_nsec];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user