GCDWebServer.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. Copyright (c) 2012-2014, Pierre-Olivier Latour
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. * Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in the
  10. documentation and/or other materials provided with the distribution.
  11. * The name of Pierre-Olivier Latour may not be used to endorse
  12. or promote products derived from this software without specific
  13. prior written permission.
  14. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. DISCLAIMED. IN NO EVENT SHALL PIERRE-OLIVIER LATOUR BE LIABLE FOR ANY
  18. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #import <TargetConditionals.h>
  26. #import "GCDWebServerRequest.h"
  27. #import "GCDWebServerResponse.h"
  28. /**
  29. * Log levels used by GCDWebServer.
  30. *
  31. * @warning kGCDWebServerLogLevel_Debug is only available if "NDEBUG" is not
  32. * defined when building.
  33. */
  34. typedef NS_ENUM(int, GCDWebServerLogLevel) {
  35. kGCDWebServerLogLevel_Debug = 0,
  36. kGCDWebServerLogLevel_Verbose,
  37. kGCDWebServerLogLevel_Info,
  38. kGCDWebServerLogLevel_Warning,
  39. kGCDWebServerLogLevel_Error,
  40. kGCDWebServerLogLevel_Exception,
  41. };
  42. /**
  43. * The GCDWebServerMatchBlock is called for every handler added to the
  44. * GCDWebServer whenever a new HTTP request has started (i.e. HTTP headers have
  45. * been received). The block is passed the basic info for the request (HTTP method,
  46. * URL, headers...) and must decide if it wants to handle it or not.
  47. *
  48. * If the handler can handle the request, the block must return a new
  49. * GCDWebServerRequest instance created with the same basic info.
  50. * Otherwise, it simply returns nil.
  51. */
  52. typedef GCDWebServerRequest* (^GCDWebServerMatchBlock)(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery);
  53. /**
  54. * The GCDWebServerProcessBlock is called after the HTTP request has been fully
  55. * received (i.e. the entire HTTP body has been read). THe block is passed the
  56. * GCDWebServerRequest created at the previous step by the GCDWebServerMatchBlock.
  57. *
  58. * The block must return a GCDWebServerResponse or nil on error, which will
  59. * result in a 500 HTTP status code returned to the client. It's however
  60. * recommended to return a GCDWebServerErrorResponse on error so more useful
  61. * information can be returned to the client.
  62. */
  63. typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(GCDWebServerRequest* request);
  64. /**
  65. * The port used by the GCDWebServer (NSNumber / NSUInteger).
  66. *
  67. * Default value is 0 i.e. let the OS pick a random port.
  68. */
  69. extern NSString* const GCDWebServerOption_Port;
  70. /**
  71. * The Bonjour name used by the GCDWebServer (NSString).
  72. *
  73. * Default value is an empty string i.e. use the computer / device name.
  74. */
  75. extern NSString* const GCDWebServerOption_BonjourName;
  76. /**
  77. * The maximum number of incoming HTTP requests that can be queued waiting to
  78. * be handled before new ones are dropped (NSNumber / NSUInteger).
  79. *
  80. * Default value is 16.
  81. */
  82. extern NSString* const GCDWebServerOption_MaxPendingConnections;
  83. /**
  84. * The value for "Server" HTTP header used by the GCDWebServer (NSString).
  85. *
  86. * Default value is the GCDWebServer class name.
  87. */
  88. extern NSString* const GCDWebServerOption_ServerName;
  89. /**
  90. * The authentication method used by the GCDWebServer
  91. * (one of "GCDWebServerAuthenticationMethod_...").
  92. *
  93. * Default value is nil i.e. authentication disabled.
  94. */
  95. extern NSString* const GCDWebServerOption_AuthenticationMethod;
  96. /**
  97. * The authentication realm used by the GCDWebServer (NSString).
  98. *
  99. * Default value is the same as GCDWebServerOption_ServerName.
  100. */
  101. extern NSString* const GCDWebServerOption_AuthenticationRealm;
  102. /**
  103. * The authentication accounts used by the GCDWebServer
  104. * (NSDictionary of username / password pairs).
  105. *
  106. * Default value is nil i.e. no accounts.
  107. */
  108. extern NSString* const GCDWebServerOption_AuthenticationAccounts;
  109. /**
  110. * The class used by the GCDWebServer when instantiating GCDWebServerConnection
  111. * (subclass of GCDWebServerConnection).
  112. *
  113. * Default value is GCDWebServerConnection class.
  114. */
  115. extern NSString* const GCDWebServerOption_ConnectionClass;
  116. /**
  117. * Allow the GCDWebServer to pretend "HEAD" requests are actually "GET" ones
  118. * and automatically discard the HTTP body of the response (NSNumber / BOOL).
  119. *
  120. * Default value is YES.
  121. */
  122. extern NSString* const GCDWebServerOption_AutomaticallyMapHEADToGET;
  123. /**
  124. * The interval expressed in seconds used by the GCDWebServer to decide how to
  125. * coalesce calls to -webServerDidConnect: and -webServerDidDisconnect:
  126. * (NSNumber / double). Coalescing will be disabled if the interval is <= 0.0.
  127. *
  128. * Default value is 1.0 second.
  129. */
  130. extern NSString* const GCDWebServerOption_ConnectedStateCoalescingInterval;
  131. #if TARGET_OS_IPHONE
  132. /**
  133. * Enables the GCDWebServer to automatically suspend itself (as if -stop was
  134. * called) when the iOS app goes into the background and the last
  135. * GCDWebServerConnection is closed, then resume itself (as if -start was called)
  136. * when the iOS app comes back to the foreground (NSNumber / BOOL).
  137. *
  138. * See the README.md file for more information about this option.
  139. *
  140. * Default value is YES.
  141. *
  142. * @warning The running property will be NO while the GCDWebServer is suspended.
  143. */
  144. extern NSString* const GCDWebServerOption_AutomaticallySuspendInBackground;
  145. #endif
  146. /**
  147. * HTTP Basic Authentication scheme (see https://tools.ietf.org/html/rfc2617).
  148. *
  149. * @warning Use of this method is not recommended as the passwords are sent in clear.
  150. */
  151. extern NSString* const GCDWebServerAuthenticationMethod_Basic;
  152. /**
  153. * HTTP Digest Access Authentication scheme (see https://tools.ietf.org/html/rfc2617).
  154. */
  155. extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
  156. @class GCDWebServer;
  157. /**
  158. * Delegate methods for GCDWebServer.
  159. *
  160. * @warning These methods are always called on the main thread in a serialized way.
  161. */
  162. @protocol GCDWebServerDelegate <NSObject>
  163. @optional
  164. /**
  165. * This method is called after the server has succesfully started.
  166. */
  167. - (void)webServerDidStart:(GCDWebServer*)server;
  168. /**
  169. * This method is called after the Bonjour registration for the server has
  170. * successfully completed.
  171. */
  172. - (void)webServerDidCompleteBonjourRegistration:(GCDWebServer*)server;
  173. /**
  174. * This method is called when the first GCDWebServerConnection is opened by the
  175. * server to serve a series of HTTP requests. A series is ongoing as long as
  176. * new HTTP requests keep coming (and new GCDWebServerConnection instances keep
  177. * being opened), before the last HTTP request has been responded to (and the
  178. * corresponding last GCDWebServerConnection closed).
  179. */
  180. - (void)webServerDidConnect:(GCDWebServer*)server;
  181. /**
  182. * This method is called when the last GCDWebServerConnection is closed after
  183. * the server has served a series of HTTP requests.
  184. *
  185. * The GCDWebServerOption_ConnectedStateCoalescingInterval option can be used
  186. * to have the server wait some extra delay before considering that the series
  187. * of HTTP requests has ended (in case there some latency between consecutive
  188. * requests). This effectively coalesces the calls to -webServerDidConnect:
  189. * and -webServerDidDisconnect:.
  190. */
  191. - (void)webServerDidDisconnect:(GCDWebServer*)server;
  192. /**
  193. * This method is called after the server has stopped.
  194. */
  195. - (void)webServerDidStop:(GCDWebServer*)server;
  196. @end
  197. /**
  198. * The GCDWebServer class manages the socket that listens for HTTP requests and
  199. * the list of handlers used to respond to them.
  200. *
  201. * See the README.md file for more information about the architecture of GCDWebServer.
  202. */
  203. @interface GCDWebServer : NSObject
  204. /**
  205. * Sets the delegate for the server.
  206. */
  207. @property(nonatomic, assign) id<GCDWebServerDelegate> delegate;
  208. /**
  209. * Indicates if the server is currently running.
  210. */
  211. @property(nonatomic, readonly, getter=isRunning) BOOL running;
  212. /**
  213. * Returns the port used by the server.
  214. *
  215. * @warning This property is only valid if the server is running.
  216. */
  217. @property(nonatomic, readonly) NSUInteger port;
  218. /**
  219. * Returns the Bonjour name in used by the server.
  220. *
  221. * @warning This property is only valid if the server is running and Bonjour
  222. * registration has successfully completed, which can take up to a few seconds.
  223. */
  224. @property(nonatomic, readonly) NSString* bonjourName;
  225. /**
  226. * This method is the designated initializer for the class.
  227. */
  228. - (instancetype)init;
  229. /**
  230. * Adds a handler to the server to handle incoming HTTP requests.
  231. * Handlers are called in a LIFO queue, so the latest added handler overrides
  232. * any previously added ones.
  233. *
  234. * @warning Addling handlers while the GCDWebServer is running is not allowed.
  235. */
  236. - (void)addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock processBlock:(GCDWebServerProcessBlock)processBlock;
  237. /**
  238. * Removes all handlers previously added to the server.
  239. *
  240. * @warning Removing handlers while the GCDWebServer is running is not allowed.
  241. */
  242. - (void)removeAllHandlers;
  243. /**
  244. * Starts the server on port 8080 (OS X & iOS Simulator) or port 80 (iOS)
  245. * using the computer / device name for as the Bonjour name.
  246. *
  247. * Returns NO if the server failed to start.
  248. */
  249. - (BOOL)start;
  250. /**
  251. * Starts the server on a given port and with a specific Bonjour name.
  252. * Pass a nil Bonjour name to disable Bonjour entirely or an empty string to
  253. * use the computer / device name.
  254. *
  255. * Returns NO if the server failed to start.
  256. */
  257. - (BOOL)startWithPort:(NSUInteger)port bonjourName:(NSString*)name;
  258. /**
  259. * Starts the server with explicit options. This method is the designated way
  260. * to start the server.
  261. *
  262. * Returns NO if the server failed to start.
  263. */
  264. - (BOOL)startWithOptions:(NSDictionary*)options;
  265. /**
  266. * Stops the server and prevents it to accepts new HTTP requests.
  267. *
  268. * @warning Stopping the server does not abort GCDWebServerConnection instances
  269. * handling already received HTTP requests. These connections will continue to
  270. * execute until the corresponding requests and responses are completed.
  271. */
  272. - (void)stop;
  273. @end
  274. @interface GCDWebServer (Extensions)
  275. /**
  276. * Returns the server's URL.
  277. *
  278. * @warning This property is only valid if the server is running.
  279. */
  280. @property(nonatomic, readonly) NSURL* serverURL;
  281. /**
  282. * Returns the server's Bonjour URL.
  283. *
  284. * @warning This property is only valid if the server is running and Bonjour
  285. * registration has successfully completed, which can take up to a few seconds.
  286. */
  287. @property(nonatomic, readonly) NSURL* bonjourServerURL;
  288. #if !TARGET_OS_IPHONE
  289. /**
  290. * Runs the server synchronously using -startWithPort:bonjourName: until a
  291. * SIGINT signal is received i.e. Ctrl-C. This method is intended to be used
  292. * by command line tools.
  293. *
  294. * Returns NO if the server failed to start.
  295. *
  296. * @warning This method must be used from the main thread only.
  297. */
  298. - (BOOL)runWithPort:(NSUInteger)port bonjourName:(NSString*)name;
  299. /**
  300. * Runs the server synchronously using -startWithOptions: until a SIGINT signal
  301. * is received i.e. Ctrl-C. This method is intended to be used by command line
  302. * tools.
  303. *
  304. * Returns NO if the server failed to start.
  305. *
  306. * @warning This method must be used from the main thread only.
  307. */
  308. - (BOOL)runWithOptions:(NSDictionary*)options;
  309. #endif
  310. @end
  311. @interface GCDWebServer (Handlers)
  312. /**
  313. * Adds a default handler to the server to handle all incoming HTTP requests
  314. * with a given HTTP method.
  315. */
  316. - (void)addDefaultHandlerForMethod:(NSString*)method requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block;
  317. /**
  318. * Adds a handler to the server to handle incoming HTTP requests with a given
  319. * HTTP method and a specific case-insensitive path.
  320. */
  321. - (void)addHandlerForMethod:(NSString*)method path:(NSString*)path requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block;
  322. /**
  323. * Adds a handler to the server to handle incoming HTTP requests with a given
  324. * HTTP method and a path matching a case-insensitive regular expression.
  325. */
  326. - (void)addHandlerForMethod:(NSString*)method pathRegex:(NSString*)regex requestClass:(Class)aClass processBlock:(GCDWebServerProcessBlock)block;
  327. @end
  328. @interface GCDWebServer (GETHandlers)
  329. /**
  330. * Adds a handler to the server to respond to incoming "GET" HTTP requests
  331. * with a specific case-insensitive path with in-memory data.
  332. */
  333. - (void)addGETHandlerForPath:(NSString*)path staticData:(NSData*)staticData contentType:(NSString*)contentType cacheAge:(NSUInteger)cacheAge;
  334. /**
  335. * Adds a handler to the server to respond to incoming "GET" HTTP requests
  336. * with a specific case-insensitive path with a file.
  337. */
  338. - (void)addGETHandlerForPath:(NSString*)path filePath:(NSString*)filePath isAttachment:(BOOL)isAttachment cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests;
  339. /**
  340. * Adds a handler to the server to respond to incoming "GET" HTTP requests
  341. * with a case-insensitive path inside a base path with the corresponding file
  342. * inside a local directory. If no local file matches the request path, a 401
  343. * HTTP status code is returned to the client.
  344. *
  345. * The "indexFilename" argument allows to specify an "index" file name to use
  346. * when the request path corresponds to a directory.
  347. */
  348. - (void)addGETHandlerForBasePath:(NSString*)basePath directoryPath:(NSString*)directoryPath indexFilename:(NSString*)indexFilename cacheAge:(NSUInteger)cacheAge allowRangeRequests:(BOOL)allowRangeRequests;
  349. @end
  350. @interface GCDWebServer (Logging)
  351. #ifndef __GCDWEBSERVER_LOGGING_HEADER__
  352. /**
  353. * Sets the current log level below which logged messages are discarded.
  354. *
  355. * The default level is either DEBUG or INFO if "NDEBUG" is defined at build-time.
  356. * It can also be set at runtime with the "logLevel" environment variable.
  357. */
  358. + (void)setLogLevel:(GCDWebServerLogLevel)level;
  359. #endif
  360. /**
  361. * Logs a message with the kGCDWebServerLogLevel_Verbose level.
  362. */
  363. - (void)logVerbose:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
  364. /**
  365. * Logs a message with the kGCDWebServerLogLevel_Info level.
  366. */
  367. - (void)logInfo:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
  368. /**
  369. * Logs a message with the kGCDWebServerLogLevel_Warning level.
  370. */
  371. - (void)logWarning:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
  372. /**
  373. * Logs a message with the kGCDWebServerLogLevel_Error level.
  374. */
  375. - (void)logError:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
  376. /**
  377. * Logs an exception with the kGCDWebServerLogLevel_Exception level.
  378. */
  379. - (void)logException:(NSException*)exception;
  380. @end
  381. #ifdef __GCDWEBSERVER_ENABLE_TESTING__
  382. @interface GCDWebServer (Testing)
  383. /**
  384. * Activates recording of HTTP requests and responses which create files in the
  385. * current directory containing the raw data for all requests and responses.
  386. *
  387. * @warning The current directory must not contain any prior recording files.
  388. */
  389. @property(nonatomic, getter=isRecordingEnabled) BOOL recordingEnabled;
  390. /**
  391. * Runs tests by playing back pre-recorded HTTP requests in the given directory
  392. * and comparing the generated responses with the pre-recorded ones.
  393. *
  394. * Returns the number of failed tests or -1 if server failed to start.
  395. */
  396. - (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)path;
  397. @end
  398. #endif