GTMHTTPServer.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* Copyright 2010 Google Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. //
  16. // GTMHTTPServer.h
  17. //
  18. // This is a *very* *simple* webserver that can be built into something, it is
  19. // not meant to stand up a site, it sends all requests to its delegate for
  20. // processing on the main thread. It does not support pipelining, etc. It's
  21. // great for places where you need a simple webserver to unittest some code
  22. // that hits a server.
  23. //
  24. // NOTE: there are several TODOs left in here as markers for things that could
  25. // be done if one wanted to add more to this class.
  26. //
  27. // Based a little on HTTPServer, part of the CocoaHTTPServer sample code found at
  28. // https://opensource.apple.com/source/HTTPServer/HTTPServer-11/CocoaHTTPServer/
  29. // License for the CocoaHTTPServer sample code:
  30. //
  31. // Software License Agreement (BSD License)
  32. //
  33. // Copyright (c) 2011, Deusty, LLC
  34. // All rights reserved.
  35. //
  36. // Redistribution and use of this software in source and binary forms,
  37. // with or without modification, are permitted provided that the following conditions are met:
  38. //
  39. // * Redistributions of source code must retain the above
  40. // copyright notice, this list of conditions and the
  41. // following disclaimer.
  42. //
  43. // * Neither the name of Deusty nor the names of its
  44. // contributors may be used to endorse or promote products
  45. // derived from this software without specific prior
  46. // written permission of Deusty, LLC.
  47. //
  48. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  49. // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  50. // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  51. // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  52. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  53. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  54. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  55. // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  56. // POSSIBILITY OF SUCH DAMAGE.
  57. #import <Foundation/Foundation.h>
  58. #if GTM_IPHONE_SDK
  59. #import <CFNetwork/CFNetwork.h>
  60. #endif // GTM_IPHONE_SDK
  61. // Global contants needed for errors from start
  62. #undef _EXTERN
  63. #undef _INITIALIZE_AS
  64. #ifdef GTMHTTPSERVER_DEFINE_GLOBALS
  65. #define _EXTERN
  66. #define _INITIALIZE_AS(x) = x
  67. #else
  68. #define _EXTERN extern
  69. #define _INITIALIZE_AS(x)
  70. #endif
  71. _EXTERN NSString *const kGTMHTTPServerErrorDomain
  72. _INITIALIZE_AS(@"com.google.mactoolbox.HTTPServerDomain");
  73. enum {
  74. kGTMHTTPServerSocketCreateFailedError = -100,
  75. kGTMHTTPServerBindFailedError = -101,
  76. kGTMHTTPServerListenFailedError = -102,
  77. kGTMHTTPServerHandleCreateFailedError = -103,
  78. };
  79. @class GTMHTTPRequestMessage, GTMHTTPResponseMessage;
  80. // ----------------------------------------------------------------------------
  81. // See comment at top of file for the intened use of this class.
  82. @interface GTMHTTPServer : NSObject {
  83. @private
  84. id delegate_; // WEAK
  85. uint16_t port_;
  86. BOOL reusePort_;
  87. BOOL localhostOnly_;
  88. NSFileHandle *listenHandle_;
  89. NSMutableArray *connections_;
  90. }
  91. // The delegate must support the httpServer:handleRequest: method in
  92. // NSObject(GTMHTTPServerDelegateMethods) below.
  93. - (id)initWithDelegate:(id)delegate;
  94. - (id)delegate;
  95. // Passing port zero will let one get assigned.
  96. - (uint16_t)port;
  97. - (void)setPort:(uint16_t)port;
  98. // Controls listening socket behavior: SO_REUSEADDR vs SO_REUSEPORT.
  99. // The default is NO (SO_REUSEADDR)
  100. - (BOOL)reusePort;
  101. - (void)setReusePort:(BOOL)reusePort;
  102. // Receive connections on the localHost loopback address only or on all
  103. // interfaces for this machine. The default is to only listen on localhost.
  104. - (BOOL)localhostOnly;
  105. - (void)setLocalhostOnly:(BOOL)yesno;
  106. // Start/Stop the web server. If there is an error starting up the server, |NO|
  107. // is returned, and the specific startup failure can be returned in |error| (see
  108. // above for the error domain and error codes). If the server is started, |YES|
  109. // is returned and the server's delegate is called for any requests that come
  110. // in.
  111. - (BOOL)start:(NSError **)error;
  112. - (void)stop;
  113. // returns the number of requests currently active in the server (i.e.-being
  114. // read in, sent replies).
  115. - (NSUInteger)activeRequestCount;
  116. @end
  117. @interface NSObject (GTMHTTPServerDelegateMethods)
  118. - (GTMHTTPResponseMessage *)httpServer:(GTMHTTPServer *)server
  119. handleRequest:(GTMHTTPRequestMessage *)request;
  120. @end
  121. // ----------------------------------------------------------------------------
  122. // Encapsulates an http request, one of these is sent to the server's delegate
  123. // for each request.
  124. @interface GTMHTTPRequestMessage : NSObject {
  125. @private
  126. CFHTTPMessageRef message_;
  127. }
  128. - (NSString *)version;
  129. - (NSURL *)URL;
  130. - (NSString *)method;
  131. - (NSData *)body;
  132. - (NSDictionary *)allHeaderFieldValues;
  133. @end
  134. // ----------------------------------------------------------------------------
  135. // Encapsulates an http response, the server's delegate should return one for
  136. // each request received.
  137. @interface GTMHTTPResponseMessage : NSObject {
  138. @private
  139. CFHTTPMessageRef message_;
  140. }
  141. + (instancetype)responseWithString:(NSString *)plainText;
  142. + (instancetype)responseWithHTMLString:(NSString *)htmlString;
  143. + (instancetype)responseWithBody:(NSData *)body
  144. contentType:(NSString *)contentType
  145. statusCode:(int)statusCode;
  146. + (instancetype)emptyResponseWithCode:(int)statusCode;
  147. // TODO: class method for redirections?
  148. // TODO: add helper for expire/no-cache
  149. - (void)setValue:(NSString *)value forHeaderField:(NSString *)headerField;
  150. - (void)setHeaderValuesFromDictionary:(NSDictionary *)dict;
  151. @end