From c51f9ad7d91184f11bc366f6d9b477c09a606b65 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Latour Date: Mon, 7 Apr 2014 19:27:58 -0700 Subject: [PATCH] Added GCDWebServerHTTPStatusCodes.h --- CGDWebServer/GCDWebServer.m | 2 +- CGDWebServer/GCDWebServerConnection.m | 22 ++--- CGDWebServer/GCDWebServerFileResponse.m | 2 +- CGDWebServer/GCDWebServerHTTPStatusCodes.h | 101 +++++++++++++++++++++ CGDWebServer/GCDWebServerPrivate.h | 2 + CGDWebServer/GCDWebServerResponse.h | 6 +- CGDWebServer/GCDWebServerResponse.m | 22 ++++- GCDWebServer.xcodeproj/project.pbxproj | 2 + 8 files changed, 143 insertions(+), 16 deletions(-) create mode 100644 CGDWebServer/GCDWebServerHTTPStatusCodes.h diff --git a/CGDWebServer/GCDWebServer.m b/CGDWebServer/GCDWebServer.m index 2370937..31ac987 100644 --- a/CGDWebServer/GCDWebServer.m +++ b/CGDWebServer/GCDWebServer.m @@ -670,7 +670,7 @@ static void _NetServiceClientCallBack(CFNetServiceRef service, CFStreamError* er if (response) { response.cacheControlMaxAge = cacheAge; } else { - response = [GCDWebServerResponse responseWithStatusCode:404]; + response = [GCDWebServerResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound]; } return response; diff --git a/CGDWebServer/GCDWebServerConnection.m b/CGDWebServer/GCDWebServerConnection.m index e1d39d5..43de7d1 100644 --- a/CGDWebServer/GCDWebServerConnection.m +++ b/CGDWebServer/GCDWebServerConnection.m @@ -458,7 +458,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { }]; } else { - [self abortRequest:_request withStatusCode:500]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; } } @@ -467,7 +467,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { NSError* error = nil; if (![_request performOpen:&error]) { LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:500]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; return; } @@ -477,7 +477,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { if (![_request performClose:&error]) { LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); } - [self abortRequest:_request withStatusCode:500]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; return; } length -= initialData.length; @@ -491,7 +491,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { [self _processRequest]; } else { LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:500]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; } }]; @@ -500,7 +500,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { [self _processRequest]; } else { LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:500]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; } } } @@ -509,7 +509,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { NSError* error = nil; if (![_request performOpen:&error]) { LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:500]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; return; } @@ -521,7 +521,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { [self _processRequest]; } else { LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error); - [self abortRequest:_request withStatusCode:500]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; } }]; @@ -572,7 +572,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { }]; } else { LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket); - [self abortRequest:_request withStatusCode:417]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed]; } } else { if (_request.usesChunkedTransferEncoding) { @@ -583,7 +583,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { } } else { LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket); - [self abortRequest:_request withStatusCode:400]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest]; } } else { [self _processRequest]; @@ -591,10 +591,10 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) { } else { _request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery]; DCHECK(_request); - [self abortRequest:_request withStatusCode:405]; + [self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_MethodNotAllowed]; } } else { - [self abortRequest:nil withStatusCode:500]; + [self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError]; } }]; diff --git a/CGDWebServer/GCDWebServerFileResponse.m b/CGDWebServer/GCDWebServerFileResponse.m index 2631c51..60e1bf6 100644 --- a/CGDWebServer/GCDWebServerFileResponse.m +++ b/CGDWebServer/GCDWebServerFileResponse.m @@ -100,7 +100,7 @@ static inline NSError* _MakePosixError(int code) { if (range.location != NSNotFound) { _offset = range.location; _size = range.length; - [self setStatusCode:206]; + [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"]; LOG_DEBUG(@"Using content bytes range [%i-%i] for file \"%@\"", (int)range.location, (int)(range.location + range.length - 1), path); } else { diff --git a/CGDWebServer/GCDWebServerHTTPStatusCodes.h b/CGDWebServer/GCDWebServerHTTPStatusCodes.h new file mode 100644 index 0000000..d64558d --- /dev/null +++ b/CGDWebServer/GCDWebServerHTTPStatusCodes.h @@ -0,0 +1,101 @@ +/* + Copyright (c) 2012-2014, Pierre-Olivier Latour + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The name of Pierre-Olivier Latour may not be used to endorse + or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html +// http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + +#import + +typedef NS_ENUM(NSInteger, GCDWebServerInformationalHTTPStatusCode) { + kGCDWebServerHTTPStatusCode_Continue = 100, + kGCDWebServerHTTPStatusCode_SwitchingProtocols = 101, + kGCDWebServerHTTPStatusCode_Processing = 102 +}; + +typedef NS_ENUM(NSInteger, GCDWebServerSuccessfulHTTPStatusCode) { + kGCDWebServerHTTPStatusCode_OK = 200, + kGCDWebServerHTTPStatusCode_Created = 201, + kGCDWebServerHTTPStatusCode_Accepted = 202, + kGCDWebServerHTTPStatusCode_NonAuthoritativeInformation = 203, + kGCDWebServerHTTPStatusCode_NoContent = 204, + kGCDWebServerHTTPStatusCode_ResetContent = 205, + kGCDWebServerHTTPStatusCode_PartialContent = 206, + kGCDWebServerHTTPStatusCode_MultiStatus = 207, + kGCDWebServerHTTPStatusCode_AlreadyReported = 208 +}; + +typedef NS_ENUM(NSInteger, GCDWebServerRedirectionHTTPStatusCode) { + kGCDWebServerHTTPStatusCode_MultipleChoices = 300, + kGCDWebServerHTTPStatusCode_MovedPermanently = 301, + kGCDWebServerHTTPStatusCode_Found = 302, + kGCDWebServerHTTPStatusCode_SeeOther = 303, + kGCDWebServerHTTPStatusCode_NotModified = 304, + kGCDWebServerHTTPStatusCode_UseProxy = 305, + kGCDWebServerHTTPStatusCode_TemporaryRedirect = 307, + kGCDWebServerHTTPStatusCode_PermanentRedirect = 308 +}; + +typedef NS_ENUM(NSInteger, GCDWebServerClientErrorHTTPStatusCode) { + kGCDWebServerHTTPStatusCode_BadRequest = 400, + kGCDWebServerHTTPStatusCode_Unauthorized = 401, + kGCDWebServerHTTPStatusCode_PaymentRequired = 402, + kGCDWebServerHTTPStatusCode_Forbidden = 403, + kGCDWebServerHTTPStatusCode_NotFound = 404, + kGCDWebServerHTTPStatusCode_MethodNotAllowed = 405, + kGCDWebServerHTTPStatusCode_NotAcceptable = 406, + kGCDWebServerHTTPStatusCode_ProxyAuthenticationRequired = 407, + kGCDWebServerHTTPStatusCode_RequestTimeout = 408, + kGCDWebServerHTTPStatusCode_Conflict = 409, + kGCDWebServerHTTPStatusCode_Gone = 410, + kGCDWebServerHTTPStatusCode_LengthRequired = 411, + kGCDWebServerHTTPStatusCode_PreconditionFailed = 412, + kGCDWebServerHTTPStatusCode_RequestEntityTooLarge = 413, + kGCDWebServerHTTPStatusCode_RequestURITooLong = 414, + kGCDWebServerHTTPStatusCode_UnsupportedMediaType = 415, + kGCDWebServerHTTPStatusCode_RequestedRangeNotSatisfiable = 416, + kGCDWebServerHTTPStatusCode_ExpectationFailed = 417, + kGCDWebServerHTTPStatusCode_UnprocessableEntity = 422, + kGCDWebServerHTTPStatusCode_Locked = 423, + kGCDWebServerHTTPStatusCode_FailedDependency = 424, + kGCDWebServerHTTPStatusCode_UpgradeRequired = 426, + kGCDWebServerHTTPStatusCode_PreconditionRequired = 428, + kGCDWebServerHTTPStatusCode_TooManyRequests = 429, + kGCDWebServerHTTPStatusCode_RequestHeaderFieldsTooLarge = 431 +}; + +typedef NS_ENUM(NSInteger, GCDWebServerServerErrorHTTPStatusCode) { + kGCDWebServerHTTPStatusCode_InternalServerError = 500, + kGCDWebServerHTTPStatusCode_NotImplemented = 501, + kGCDWebServerHTTPStatusCode_BadGateway = 502, + kGCDWebServerHTTPStatusCode_ServiceUnavailable = 503, + kGCDWebServerHTTPStatusCode_GatewayTimeout = 504, + kGCDWebServerHTTPStatusCode_HTTPVersionNotSupported = 505, + kGCDWebServerHTTPStatusCode_InsufficientStorage = 507, + kGCDWebServerHTTPStatusCode_LoopDetected = 508, + kGCDWebServerHTTPStatusCode_NotExtended = 510, + kGCDWebServerHTTPStatusCode_NetworkAuthenticationRequired = 511 +}; diff --git a/CGDWebServer/GCDWebServerPrivate.h b/CGDWebServer/GCDWebServerPrivate.h index 7e320ee..736828e 100644 --- a/CGDWebServer/GCDWebServerPrivate.h +++ b/CGDWebServer/GCDWebServerPrivate.h @@ -50,6 +50,8 @@ #define ARC_DISPATCH_RELEASE(__OBJECT__) dispatch_release(__OBJECT__) #endif +#import "GCDWebServerHTTPStatusCodes.h" + #import "GCDWebServerConnection.h" #import "GCDWebServerDataRequest.h" diff --git a/CGDWebServer/GCDWebServerResponse.h b/CGDWebServer/GCDWebServerResponse.h index cee967e..4892535 100644 --- a/CGDWebServer/GCDWebServerResponse.h +++ b/CGDWebServer/GCDWebServerResponse.h @@ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import +#import "GCDWebServerHTTPStatusCodes.h" @protocol GCDWebServerBodyReader - (BOOL)open:(NSError**)error; // Return NO on error ("error" is guaranteed to be non-NULL) @@ -47,7 +47,11 @@ @interface GCDWebServerResponse (Extensions) + (GCDWebServerResponse*)responseWithStatusCode:(NSInteger)statusCode; ++ (GCDWebServerResponse*)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)error; ++ (GCDWebServerResponse*)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)error; + (GCDWebServerResponse*)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent; - (id)initWithStatusCode:(NSInteger)statusCode; +- (id)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)error; +- (id)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)error; - (id)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent; @end diff --git a/CGDWebServer/GCDWebServerResponse.m b/CGDWebServer/GCDWebServerResponse.m index a12fe9b..71f65ab 100644 --- a/CGDWebServer/GCDWebServerResponse.m +++ b/CGDWebServer/GCDWebServerResponse.m @@ -179,7 +179,7 @@ if ((self = [super init])) { _type = nil; _length = NSNotFound; - _status = 200; + _status = kGCDWebServerHTTPStatusCode_OK; _maxAge = 0; _headers = [[NSMutableDictionary alloc] init]; _encoders = [[NSMutableArray alloc] init]; @@ -253,6 +253,14 @@ return ARC_AUTORELEASE([[self alloc] initWithStatusCode:statusCode]); } ++ (GCDWebServerResponse*)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)error { + return ARC_AUTORELEASE([[self alloc] initWithClientError:error]); +} + ++ (GCDWebServerResponse*)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)error { + return ARC_AUTORELEASE([[self alloc] initWithServerError:error]); +} + + (GCDWebServerResponse*)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent { return ARC_AUTORELEASE([[self alloc] initWithRedirect:location permanent:permanent]); } @@ -264,9 +272,19 @@ return self; } +- (id)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)error { + DCHECK(((NSInteger)error >= 400) && ((NSInteger)error < 500)); + return [self initWithStatusCode:error]; +} + +- (id)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)error { + DCHECK(((NSInteger)error >= 500) && ((NSInteger)error < 600)); + return [self initWithStatusCode:error]; +} + - (id)initWithRedirect:(NSURL*)location permanent:(BOOL)permanent { if ((self = [self init])) { - self.statusCode = permanent ? 301 : 307; + self.statusCode = permanent ? kGCDWebServerHTTPStatusCode_MovedPermanently : kGCDWebServerHTTPStatusCode_TemporaryRedirect; [self setValue:[location absoluteString] forAdditionalHeader:@"Location"]; } return self; diff --git a/GCDWebServer.xcodeproj/project.pbxproj b/GCDWebServer.xcodeproj/project.pbxproj index 7fcb148..8e9e4a9 100644 --- a/GCDWebServer.xcodeproj/project.pbxproj +++ b/GCDWebServer.xcodeproj/project.pbxproj @@ -127,6 +127,7 @@ E2A0E80018F1D3DE00C580B1 /* GCDWebServerMultiPartFormRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDWebServerMultiPartFormRequest.m; sourceTree = ""; }; E2A0E80318F1D4A700C580B1 /* GCDWebServerURLEncodedFormRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDWebServerURLEncodedFormRequest.h; sourceTree = ""; }; E2A0E80418F1D4A700C580B1 /* GCDWebServerURLEncodedFormRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDWebServerURLEncodedFormRequest.m; sourceTree = ""; }; + E2A0E81018F3737B00C580B1 /* GCDWebServerHTTPStatusCodes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCDWebServerHTTPStatusCodes.h; sourceTree = ""; }; E2B0D4A618F13495009A7927 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; E2B0D4A818F134A8009A7927 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; }; E2BE850718E77ECA0061360B /* GCDWebUploader.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = GCDWebUploader.bundle; sourceTree = ""; }; @@ -199,6 +200,7 @@ E2A0E7FC18F1D36C00C580B1 /* GCDWebServerFileRequest.m */, E2A0E7EF18F1D12E00C580B1 /* GCDWebServerFileResponse.h */, E2A0E7F018F1D12E00C580B1 /* GCDWebServerFileResponse.m */, + E2A0E81018F3737B00C580B1 /* GCDWebServerHTTPStatusCodes.h */, E2A0E7FF18F1D3DE00C580B1 /* GCDWebServerMultiPartFormRequest.h */, E2A0E80018F1D3DE00C580B1 /* GCDWebServerMultiPartFormRequest.m */, E22112801690B63A0048D2B2 /* GCDWebServerPrivate.h */,