From 0807cf5fe61d387d81c10dfb4df81cc394a81e85 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Latour Date: Sat, 19 Apr 2014 17:39:09 -0300 Subject: [PATCH] #33 Documented Requests/ and Responses/ --- GCDWebServer/Core/GCDWebServerRequest.h | 4 +- GCDWebServer/Core/GCDWebServerResponse.h | 6 +- .../Requests/GCDWebServerDataRequest.h | 27 ++++++- .../Requests/GCDWebServerFileRequest.h | 13 ++++ .../GCDWebServerMultiPartFormRequest.h | 74 ++++++++++++++++++- .../GCDWebServerURLEncodedFormRequest.h | 20 ++++- .../Responses/GCDWebServerDataResponse.h | 65 +++++++++++++++- .../Responses/GCDWebServerErrorResponse.h | 42 ++++++++++- .../Responses/GCDWebServerFileResponse.h | 58 ++++++++++++++- .../Responses/GCDWebServerStreamingResponse.h | 20 ++++- README.md | 6 +- 11 files changed, 315 insertions(+), 20 deletions(-) diff --git a/GCDWebServer/Core/GCDWebServerRequest.h b/GCDWebServer/Core/GCDWebServerRequest.h index bcbbf39..46d9779 100644 --- a/GCDWebServer/Core/GCDWebServerRequest.h +++ b/GCDWebServer/Core/GCDWebServerRequest.h @@ -126,12 +126,12 @@ @property(nonatomic, readonly) NSUInteger contentLength; /** - * Returns the parsed "If-Modified-Since" header or nil if absent of malformed. + * Returns the parsed "If-Modified-Since" header or nil if absent or malformed. */ @property(nonatomic, readonly) NSDate* ifModifiedSince; /** - * Returns the parsed "If-None-Match" header or nil if absent of malformed. + * Returns the parsed "If-None-Match" header or nil if absent or malformed. */ @property(nonatomic, readonly) NSString* ifNoneMatch; diff --git a/GCDWebServer/Core/GCDWebServerResponse.h b/GCDWebServer/Core/GCDWebServerResponse.h index 80e34a2..bbe5686 100644 --- a/GCDWebServer/Core/GCDWebServerResponse.h +++ b/GCDWebServer/Core/GCDWebServerResponse.h @@ -138,7 +138,7 @@ @property(nonatomic, getter=isGZipContentEncodingEnabled) BOOL gzipContentEncodingEnabled; /** - * Creates a default response. + * Creates an empty response. */ + (instancetype)response; @@ -166,7 +166,7 @@ @interface GCDWebServerResponse (Extensions) /** - * Creates a default response with a specific HTTP status code. + * Creates a empty response with a specific HTTP status code. */ + (instancetype)responseWithStatusCode:(NSInteger)statusCode; @@ -176,7 +176,7 @@ + (instancetype)responseWithRedirect:(NSURL*)location permanent:(BOOL)permanent; /** - * Initializes a default response with a specific HTTP status code. + * Initializes an empty response with a specific HTTP status code. */ - (instancetype)initWithStatusCode:(NSInteger)statusCode; diff --git a/GCDWebServer/Requests/GCDWebServerDataRequest.h b/GCDWebServer/Requests/GCDWebServerDataRequest.h index 02b078f..ef94b97 100644 --- a/GCDWebServer/Requests/GCDWebServerDataRequest.h +++ b/GCDWebServer/Requests/GCDWebServerDataRequest.h @@ -27,11 +27,34 @@ #import "GCDWebServerRequest.h" +/** + * The GCDWebServerDataRequest subclass of GCDWebServerRequest stores the body + * of the HTTP request in memory. + */ @interface GCDWebServerDataRequest : GCDWebServerRequest + +/** + * Returns the data for the request body. + */ @property(nonatomic, readonly) NSData* data; + @end @interface GCDWebServerDataRequest (Extensions) -@property(nonatomic, readonly) NSString* text; // Text encoding is extracted from Content-Type or defaults to UTF-8 - Returns nil on error -@property(nonatomic, readonly) id jsonObject; // Returns nil on error + +/** + * Returns the data for the request body interpreted as text. If the content + * type of the body is not a text one, or if an error occurs, nil is returned. + * + * The text encoding used to interpret the data is extracted from the + * "Content-Type" header or defaults to UTF-8. + */ +@property(nonatomic, readonly) NSString* text; + +/** + * Returns the data for the request body interpreted as a JSON object. If the + * content type of the body is not JSON, or if an error occurs, nil is returned. + */ +@property(nonatomic, readonly) id jsonObject; + @end diff --git a/GCDWebServer/Requests/GCDWebServerFileRequest.h b/GCDWebServer/Requests/GCDWebServerFileRequest.h index 94cb4c2..427a800 100644 --- a/GCDWebServer/Requests/GCDWebServerFileRequest.h +++ b/GCDWebServer/Requests/GCDWebServerFileRequest.h @@ -27,6 +27,19 @@ #import "GCDWebServerRequest.h" +/** + * The GCDWebServerFileRequest subclass of GCDWebServerRequest stores the body + * of the HTTP request to a file on disk. + */ @interface GCDWebServerFileRequest : GCDWebServerRequest + +/** + * Returns the path to the temporary file containing the request body. + * + * @warning This temporary file will be automatically deleted when the + * GCDWebServerFileRequest is deallocated. If you want to preserve this file, + * you must move it to a different location beforehand. + */ @property(nonatomic, readonly) NSString* temporaryPath; + @end diff --git a/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h b/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h index 3e94214..043014e 100644 --- a/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h +++ b/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h @@ -27,23 +27,91 @@ #import "GCDWebServerRequest.h" +/** + * The GCDWebServerMultiPart class is an abstract class that wraps the content + * of a part. + */ @interface GCDWebServerMultiPart : NSObject -@property(nonatomic, readonly) NSString* contentType; // Defaults to "text/plain" per specification if undefined + +/** + * Returns the content type retrieved from the part headers or "text/plain" + * if not available (per HTTP specifications). + */ +@property(nonatomic, readonly) NSString* contentType; + +/** + * Returns the MIME type component of the content type for the part. + */ @property(nonatomic, readonly) NSString* mimeType; + @end +/** + * The GCDWebServerMultiPartArgument subclass of GCDWebServerMultiPart wraps + * the content of a part as data in memory. + */ @interface GCDWebServerMultiPartArgument : GCDWebServerMultiPart + +/** + * Returns the data for the part. + */ @property(nonatomic, readonly) NSData* data; -@property(nonatomic, readonly) NSString* string; // May be nil (only valid for text mime types) + +/** + * Returns the data for the part interpreted as text. If the content + * type of the part is not a text one, or if an error occurs, nil is returned. + * + * The text encoding used to interpret the data is extracted from the + * "Content-Type" header or defaults to UTF-8. + */ +@property(nonatomic, readonly) NSString* string; + @end +/** + * The GCDWebServerMultiPartFile subclass of GCDWebServerMultiPart wraps + * the content of a part as a file on disk. + */ @interface GCDWebServerMultiPartFile : GCDWebServerMultiPart -@property(nonatomic, readonly) NSString* fileName; // May be nil + +/** + * Returns the file name retrieved from the part headers. + */ +@property(nonatomic, readonly) NSString* fileName; + +/** + * Returns the path to the temporary file containing the part data. + * + * @warning This temporary file will be automatically deleted when the + * GCDWebServerMultiPartFile is deallocated. If you want to preserve this file, + * you must move it to a different location beforehand. + */ @property(nonatomic, readonly) NSString* temporaryPath; + @end +/** + * The GCDWebServerMultiPartFormRequest subclass of GCDWebServerRequest + * parses the body of the HTTP request as a multipart encoded form. + */ @interface GCDWebServerMultiPartFormRequest : GCDWebServerRequest + +/** + * Returns the argument parts from the multipart encoded form as + * name / GCDWebServerMultiPartArgument pairs. + */ @property(nonatomic, readonly) NSDictionary* arguments; + +/** + * Returns the files parts from the multipart encoded form as + * name / GCDWebServerMultiPartFile pairs. + */ @property(nonatomic, readonly) NSDictionary* files; + +/** + * Returns the MIME type for multipart encoded forms + * i.e. "multipart/form-data". + */ + (NSString*)mimeType; + @end diff --git a/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h b/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h index 9615e8e..edb858f 100644 --- a/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h +++ b/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h @@ -27,7 +27,25 @@ #import "GCDWebServerDataRequest.h" +/** + * The GCDWebServerURLEncodedFormRequest subclass of GCDWebServerRequest + * parses the body of the HTTP request as a URL encoded form using + * GCDWebServerParseURLEncodedForm(). + */ @interface GCDWebServerURLEncodedFormRequest : GCDWebServerDataRequest -@property(nonatomic, readonly) NSDictionary* arguments; // Text encoding is extracted from Content-Type or defaults to UTF-8 + +/** + * Returns the unescaped names and values for the URL encoded form. + * + * The text encoding used to interpret the data is extracted from the + * "Content-Type" header or defaults to UTF-8. + */ +@property(nonatomic, readonly) NSDictionary* arguments; + +/** + * Returns the MIME type for URL encoded forms + * i.e. "application/x-www-form-urlencoded". + */ + (NSString*)mimeType; + @end diff --git a/GCDWebServer/Responses/GCDWebServerDataResponse.h b/GCDWebServer/Responses/GCDWebServerDataResponse.h index deca337..eb9cfca 100644 --- a/GCDWebServer/Responses/GCDWebServerDataResponse.h +++ b/GCDWebServer/Responses/GCDWebServerDataResponse.h @@ -27,20 +27,81 @@ #import "GCDWebServerResponse.h" +/** + * The GCDWebServerDataResponse subclass of GCDWebServerResponse reads the body + * of the HTTP response from memory. + */ @interface GCDWebServerDataResponse : GCDWebServerResponse + +/** + * Creates a response with data in memory and a given content type. + */ + (instancetype)responseWithData:(NSData*)data contentType:(NSString*)type; + +/** + * This method is the designated initializer for the class. + */ - (instancetype)initWithData:(NSData*)data contentType:(NSString*)type; + @end @interface GCDWebServerDataResponse (Extensions) + +/** + * Creates a data response from text encoded using UTF-8. + */ + (instancetype)responseWithText:(NSString*)text; + +/** + * Creates a data response from HTML encoded using UTF-8. + */ + (instancetype)responseWithHTML:(NSString*)html; + +/** + * Creates a data response from an HTML template encoded using UTF-8. + * See -initWithHTMLTemplate:variables: for details. + */ + (instancetype)responseWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; + +/** + * Creates a data response from a serialized JSON object and the default + * "application/json" content type. + */ + (instancetype)responseWithJSONObject:(id)object; + +/** + * Creates a data response from a serialized JSON object and a custom + * content type. + */ + (instancetype)responseWithJSONObject:(id)object contentType:(NSString*)type; + +/** + * Initializes a data response from text encoded using UTF-8. + */ - (instancetype)initWithText:(NSString*)text; // Encodes using UTF-8 -- (instancetype)initWithHTML:(NSString*)html; // Encodes using UTF-8 -- (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; // Simple template system that replaces all occurences of "%variable%" with corresponding value (encodes using UTF-8) + +/** + * Initializes a data response from HTML encoded using UTF-8. + */ +- (instancetype)initWithHTML:(NSString*)html; + +/** + * Initializes a data response from an HTML template encoded using UTF-8. + * All occurences of "%variable%" within the HTML template are replaced with + * their corresponding values. + */ +- (instancetype)initWithHTMLTemplate:(NSString*)path variables:(NSDictionary*)variables; + +/** + * Initializes a data response from a serialized JSON object and the default + * "application/json" content type. + */ - (instancetype)initWithJSONObject:(id)object; + +/** + * Initializes a data response from a serialized JSON object and a custom + * content type. + */ - (instancetype)initWithJSONObject:(id)object contentType:(NSString*)type; + @end diff --git a/GCDWebServer/Responses/GCDWebServerErrorResponse.h b/GCDWebServer/Responses/GCDWebServerErrorResponse.h index 98cbeee..5d15e8b 100644 --- a/GCDWebServer/Responses/GCDWebServerErrorResponse.h +++ b/GCDWebServer/Responses/GCDWebServerErrorResponse.h @@ -28,14 +28,54 @@ #import "GCDWebServerDataResponse.h" #import "GCDWebServerHTTPStatusCodes.h" -// Returns responses with an HTML body containing the error message +/** + * The GCDWebServerDataResponse subclass of GCDWebServerDataResponse generates + * an HTML body from an HTTP status code and an error message. + */ @interface GCDWebServerErrorResponse : GCDWebServerDataResponse + +/** + * Creates a client error response with the corresponding HTTP status code. + */ + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); + +/** + * Creates a server error response with the corresponding HTTP status code. + */ + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); + +/** + * Creates a client error response with the corresponding HTTP status code + * and an optional underlying NSError. + */ + (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); + +/** + * Creates a server error response with the corresponding HTTP status code + * and an optional underlying NSError. + */ + (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); + +/** + * Initializes a client error response with the corresponding HTTP status code. + */ - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); + +/** + * Initializes a server error response with the corresponding HTTP status code. + */ - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... NS_FORMAT_FUNCTION(2,3); + +/** + * Initializes a client error response with the corresponding HTTP status code + * and an optional underlying NSError. + */ - (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); + +/** + * Initializes a server error response with the corresponding HTTP status code + * and an optional underlying NSError. + */ - (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... NS_FORMAT_FUNCTION(3,4); + @end diff --git a/GCDWebServer/Responses/GCDWebServerFileResponse.h b/GCDWebServer/Responses/GCDWebServerFileResponse.h index 9d0efef..aa1e3f7 100644 --- a/GCDWebServer/Responses/GCDWebServerFileResponse.h +++ b/GCDWebServer/Responses/GCDWebServerFileResponse.h @@ -27,13 +27,67 @@ #import "GCDWebServerResponse.h" +/** + * The GCDWebServerFileResponse subclass of GCDWebServerResponse reads the body + * of the HTTP response from a file on disk. + */ @interface GCDWebServerFileResponse : GCDWebServerResponse + +/** + * Creates a response with the contents of a file and the content type + * automatically set from the file extension. + */ + (instancetype)responseWithFile:(NSString*)path; + +/** + * Creates a response like +responseWithFile: but sets the "Content-Disposition" + * HTTP header appropriately for a download if the "attachment" argument is YES. + */ + (instancetype)responseWithFile:(NSString*)path isAttachment:(BOOL)attachment; + +/** + * Creates a response like +responseWithFile: but restricts the file contents + * to a specific byte range. + * + * See -initWithFile:byteRange: for details. + */ + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range; + +/** + * Creates a response like +responseWithFile:byteRange: but also sets the + * "Content-Disposition" HTTP header appropriately for a download if the + * "attachment" argument is YES. + */ + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; + +/** + * Initializes a response with the contents of a file and the content type + * automatically set from the file extension. + */ - (instancetype)initWithFile:(NSString*)path; -- (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment; // If in attachment mode, "Content-Disposition" header will be set accordingly -- (instancetype)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, -length] from end of file + +/** + * Initializes a response like -initWithFile: but sets the "Content-Disposition" + * HTTP header appropriately for a download if the "attachment" argument is YES. + */ +- (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment; + +/** + * Initializes a response like -initWithFile: but restricts the file contents + * to a specific byte range. This range should be set to (NSNotFound, 0) for + * 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" + * and "length" values will be automatically adjusted to be compatible with the + * actual size of the file. + * + * This argument would typically be set to the value of the byteRange property + * of the current GCDWebServerRequest. + */ +- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range; + +/** + * This method is the designated initializer for the class. + */ - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; + @end diff --git a/GCDWebServer/Responses/GCDWebServerStreamingResponse.h b/GCDWebServer/Responses/GCDWebServerStreamingResponse.h index 52e7a28..fc2b6e0 100644 --- a/GCDWebServer/Responses/GCDWebServerStreamingResponse.h +++ b/GCDWebServer/Responses/GCDWebServerStreamingResponse.h @@ -27,9 +27,27 @@ #import "GCDWebServerStreamingResponse.h" +/** + * 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. + */ typedef NSData* (^GCDWebServerStreamBlock)(NSError** error); +/** + * The GCDWebServerStreamingResponse subclass of GCDWebServerResponse streams + * the body of the HTTP response using a GCD block. + */ @interface GCDWebServerStreamingResponse : GCDWebServerResponse + +/** + * Creates a response with streamed data and a given content type. + */ + (instancetype)responseWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block; -- (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block; // Block must return empty NSData when done or nil on error and set the "error" argument accordingly + +/** + * This method is the designated initializer for the class. + */ +- (instancetype)initWithContentType:(NSString*)type streamBlock:(GCDWebServerStreamBlock)block; + @end diff --git a/README.md b/README.md index 8c5b284..0ccaffc 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ Overview [![Build Status](https://travis-ci.org/swisspol/GCDWebServer.svg?branch=master)](https://travis-ci.org/swisspol/GCDWebServer) GCDWebServer is a modern and lightweight GCD based HTTP 1.1 server designed to be embedded in OS X & iOS apps. It was written from scratch with the following goals in mind: -* Easy to use and understand architecture with only 4 core classes: server, connection, request and response (see "Understanding GCDWebServer's Architecture" below) -* Well designed API for easy integration and customization -* Entirely built with an event-driven design using [Grand Central Dispatch](http://en.wikipedia.org/wiki/Grand_Central_Dispatch) for maximal performance and concurrency +* Elegant and easy to use architecture with only 4 core classes: server, connection, request and response (see "Understanding GCDWebServer's Architecture" below) +* Well designed API with fully documented headers for easy integration and customization +* Entirely built with an event-driven design using [Grand Central Dispatch](http://en.wikipedia.org/wiki/Grand_Central_Dispatch) for best performance and concurrency * No dependencies on third-party source code * Available under a friendly [New BSD License](LICENSE)