CivetServer.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. /* Copyright (c) 2013-2017 the Civetweb developers
  2. * Copyright (c) 2013 No Face Press, LLC
  3. *
  4. * License http://opensource.org/licenses/mit-license.php MIT License
  5. */
  6. #ifndef CIVETSERVER_HEADER_INCLUDED
  7. #define CIVETSERVER_HEADER_INCLUDED
  8. #ifdef __cplusplus
  9. #include "civetweb.h"
  10. #include <map>
  11. #include <stdexcept>
  12. #include <string>
  13. #include <vector>
  14. #ifndef CIVETWEB_CXX_API
  15. #if defined(_WIN32)
  16. #if defined(CIVETWEB_CXX_DLL_EXPORTS)
  17. #define CIVETWEB_CXX_API __declspec(dllexport)
  18. #elif defined(CIVETWEB_CXX_DLL_IMPORTS)
  19. #define CIVETWEB_CXX_API __declspec(dllimport)
  20. #else
  21. #define CIVETWEB_CXX_API
  22. #endif
  23. #elif __GNUC__ >= 4
  24. #define CIVETWEB_CXX_API __attribute__((visibility("default")))
  25. #else
  26. #define CIVETWEB_CXX_API
  27. #endif
  28. #endif
  29. // forward declaration
  30. class CivetServer;
  31. /**
  32. * Exception class for thrown exceptions within the CivetHandler object.
  33. */
  34. class CIVETWEB_CXX_API CivetException : public std::runtime_error
  35. {
  36. public:
  37. CivetException(const std::string &msg) : std::runtime_error(msg)
  38. {
  39. }
  40. };
  41. /**
  42. * Basic interface for a URI request handler. Handlers implementations
  43. * must be reentrant.
  44. */
  45. class CIVETWEB_CXX_API CivetHandler
  46. {
  47. public:
  48. /**
  49. * Destructor
  50. */
  51. virtual ~CivetHandler()
  52. {
  53. }
  54. /**
  55. * Callback method for GET request.
  56. *
  57. * @param server - the calling server
  58. * @param conn - the connection information
  59. * @returns true if implemented, false otherwise
  60. */
  61. virtual bool handleGet(CivetServer *server, struct mg_connection *conn);
  62. /**
  63. * Callback method for GET request.
  64. *
  65. * @param server - the calling server
  66. * @param conn - the connection information
  67. * @param http - pointer to return status code
  68. * @returns true if implemented, false otherwise
  69. */
  70. virtual bool handleGet(CivetServer *server, struct mg_connection *conn, int *status_code);
  71. /**
  72. * Callback method for POST request.
  73. *
  74. * @param server - the calling server
  75. * @param conn - the connection information
  76. * @returns true if implemented, false otherwise
  77. */
  78. virtual bool handlePost(CivetServer *server, struct mg_connection *conn);
  79. /**
  80. * Callback method for POST request.
  81. *
  82. * @param server - the calling server
  83. * @param conn - the connection information
  84. * @param http - pointer to return status code
  85. * @returns true if implemented, false otherwise
  86. */
  87. virtual bool handlePost(CivetServer *server, struct mg_connection *conn, int *status_code);
  88. /**
  89. * Callback method for HEAD request.
  90. *
  91. * @param server - the calling server
  92. * @param conn - the connection information
  93. * @returns true if implemented, false otherwise
  94. */
  95. virtual bool handleHead(CivetServer *server, struct mg_connection *conn);
  96. /**
  97. * Callback method for HEAD request.
  98. *
  99. * @param server - the calling server
  100. * @param conn - the connection information
  101. * @param http - pointer to return status code
  102. * @returns true if implemented, false otherwise
  103. */
  104. virtual bool handleHead(CivetServer *server, struct mg_connection *conn, int *status_code);
  105. /**
  106. * Callback method for PUT request.
  107. *
  108. * @param server - the calling server
  109. * @param conn - the connection information
  110. * @returns true if implemented, false otherwise
  111. */
  112. virtual bool handlePut(CivetServer *server, struct mg_connection *conn);
  113. /**
  114. * Callback method for PUT request.
  115. *
  116. * @param server - the calling server
  117. * @param conn - the connection information
  118. * @param http - pointer to return status code
  119. * @returns true if implemented, false otherwise
  120. */
  121. virtual bool handlePut(CivetServer *server, struct mg_connection *conn, int *status_code);
  122. /**
  123. * Callback method for DELETE request.
  124. *
  125. * @param server - the calling server
  126. * @param conn - the connection information
  127. * @returns true if implemented, false otherwise
  128. */
  129. virtual bool handleDelete(CivetServer *server, struct mg_connection *conn);
  130. /**
  131. * Callback method for DELETE request.
  132. *
  133. * @param server - the calling server
  134. * @param conn - the connection information
  135. * @param http - pointer to return status code
  136. * @returns true if implemented, false otherwise
  137. */
  138. virtual bool handleDelete(CivetServer *server, struct mg_connection *conn, int *status_code);
  139. /**
  140. * Callback method for OPTIONS request.
  141. *
  142. * @param server - the calling server
  143. * @param conn - the connection information
  144. * @returns true if implemented, false otherwise
  145. */
  146. virtual bool handleOptions(CivetServer *server, struct mg_connection *conn);
  147. /**
  148. * Callback method for OPTIONS request.
  149. *
  150. * @param server - the calling server
  151. * @param conn - the connection information
  152. * @param http - pointer to return status code
  153. * @returns true if implemented, false otherwise
  154. */
  155. virtual bool handleOptions(CivetServer *server, struct mg_connection *conn, int *status_code);
  156. /**
  157. * Callback method for PATCH request.
  158. *
  159. * @param server - the calling server
  160. * @param conn - the connection information
  161. * @returns true if implemented, false otherwise
  162. */
  163. virtual bool handlePatch(CivetServer *server, struct mg_connection *conn);
  164. /**
  165. * Callback method for PATCH request.
  166. *
  167. * @param server - the calling server
  168. * @param conn - the connection information
  169. * @param http - pointer to return status code
  170. * @returns true if implemented, false otherwise
  171. */
  172. virtual bool handlePatch(CivetServer *server, struct mg_connection *conn, int *status_code);
  173. };
  174. /**
  175. * Basic interface for a URI authorization handler. Handler implementations
  176. * must be reentrant.
  177. */
  178. class CIVETWEB_CXX_API CivetAuthHandler
  179. {
  180. public:
  181. /**
  182. * Destructor
  183. */
  184. virtual ~CivetAuthHandler()
  185. {
  186. }
  187. /**
  188. * Callback method for authorization requests. It is up the this handler
  189. * to generate 401 responses if authorization fails.
  190. *
  191. * @param server - the calling server
  192. * @param conn - the connection information
  193. * @returns true if authorization succeeded, false otherwise
  194. */
  195. virtual bool authorize(CivetServer *server, struct mg_connection *conn) = 0;
  196. };
  197. /**
  198. * Basic interface for a websocket handler. Handlers implementations
  199. * must be reentrant.
  200. */
  201. class CIVETWEB_CXX_API CivetWebSocketHandler
  202. {
  203. public:
  204. /**
  205. * Destructor
  206. */
  207. virtual ~CivetWebSocketHandler()
  208. {
  209. }
  210. /**
  211. * Callback method for when the client intends to establish a websocket
  212. *connection, before websocket handshake.
  213. *
  214. * @param server - the calling server
  215. * @param conn - the connection information
  216. * @returns true to keep socket open, false to close it
  217. */
  218. virtual bool handleConnection(CivetServer *server,
  219. const struct mg_connection *conn);
  220. /**
  221. * Callback method for when websocket handshake is successfully completed,
  222. *and connection is ready for data exchange.
  223. *
  224. * @param server - the calling server
  225. * @param conn - the connection information
  226. */
  227. virtual void handleReadyState(CivetServer *server,
  228. struct mg_connection *conn);
  229. /**
  230. * Callback method for when a data frame has been received from the client.
  231. *
  232. * @param server - the calling server
  233. * @param conn - the connection information
  234. * @bits: first byte of the websocket frame, see websocket RFC at
  235. *http://tools.ietf.org/html/rfc6455, section 5.2
  236. * @data, data_len: payload, with mask (if any) already applied.
  237. * @returns true to keep socket open, false to close it
  238. */
  239. virtual bool handleData(CivetServer *server,
  240. struct mg_connection *conn,
  241. int bits,
  242. char *data,
  243. size_t data_len);
  244. /**
  245. * Callback method for when the connection is closed.
  246. *
  247. * @param server - the calling server
  248. * @param conn - the connection information
  249. */
  250. virtual void handleClose(CivetServer *server,
  251. const struct mg_connection *conn);
  252. };
  253. /**
  254. * CivetCallbacks
  255. *
  256. * wrapper for mg_callbacks
  257. */
  258. struct CIVETWEB_CXX_API CivetCallbacks : public mg_callbacks {
  259. CivetCallbacks();
  260. };
  261. /**
  262. * CivetServer
  263. *
  264. * Basic class for embedded web server. This has an URL mapping built-in.
  265. */
  266. class CIVETWEB_CXX_API CivetServer
  267. {
  268. public:
  269. /**
  270. * Constructor
  271. *
  272. * This automatically starts the sever.
  273. * It is good practice to call getContext() after this in case there
  274. * were errors starting the server.
  275. *
  276. * Note: CivetServer should not be used as a static instance in a Windows
  277. * DLL, since the constructor creates threads and the destructor joins
  278. * them again (creating/joining threads should not be done in static
  279. * constructors).
  280. *
  281. * @param options - the web server options.
  282. * @param callbacks - optional web server callback methods.
  283. *
  284. * @throws CivetException
  285. */
  286. CivetServer(const char **options,
  287. const struct CivetCallbacks *callbacks = 0,
  288. const void *UserContext = 0);
  289. CivetServer(const std::vector<std::string> &options,
  290. const struct CivetCallbacks *callbacks = 0,
  291. const void *UserContext = 0);
  292. /**
  293. * Destructor
  294. */
  295. virtual ~CivetServer();
  296. /**
  297. * close()
  298. *
  299. * Stops server and frees resources.
  300. */
  301. void close();
  302. /**
  303. * getContext()
  304. *
  305. * @return the context or 0 if not running.
  306. */
  307. const struct mg_context *
  308. getContext() const
  309. {
  310. return context;
  311. }
  312. /**
  313. * addHandler(const std::string &, CivetHandler *)
  314. *
  315. * Adds a URI handler. If there is existing URI handler, it will
  316. * be replaced with this one.
  317. *
  318. * URI's are ordered and prefix (REST) URI's are supported.
  319. *
  320. * @param uri - URI to match.
  321. * @param handler - handler instance to use.
  322. */
  323. void addHandler(const std::string &uri, CivetHandler *handler);
  324. void
  325. addHandler(const std::string &uri, CivetHandler &handler)
  326. {
  327. addHandler(uri, &handler);
  328. }
  329. /**
  330. * addWebSocketHandler
  331. *
  332. * Adds a WebSocket handler for a specific URI. If there is existing URI
  333. *handler, it will
  334. * be replaced with this one.
  335. *
  336. * URI's are ordered and prefix (REST) URI's are supported.
  337. *
  338. * @param uri - URI to match.
  339. * @param handler - handler instance to use.
  340. */
  341. void addWebSocketHandler(const std::string &uri,
  342. CivetWebSocketHandler *handler);
  343. void
  344. addWebSocketHandler(const std::string &uri, CivetWebSocketHandler &handler)
  345. {
  346. addWebSocketHandler(uri, &handler);
  347. }
  348. /**
  349. * removeHandler(const std::string &)
  350. *
  351. * Removes a handler.
  352. *
  353. * @param uri - the exact URL used in addHandler().
  354. */
  355. void removeHandler(const std::string &uri);
  356. /**
  357. * removeWebSocketHandler(const std::string &)
  358. *
  359. * Removes a web socket handler.
  360. *
  361. * @param uri - the exact URL used in addWebSocketHandler().
  362. */
  363. void removeWebSocketHandler(const std::string &uri);
  364. /**
  365. * addAuthHandler(const std::string &, CivetAuthHandler *)
  366. *
  367. * Adds a URI authorization handler. If there is existing URI authorization
  368. * handler, it will be replaced with this one.
  369. *
  370. * URI's are ordered and prefix (REST) URI's are supported.
  371. *
  372. * @param uri - URI to match.
  373. * @param handler - authorization handler instance to use.
  374. */
  375. void addAuthHandler(const std::string &uri, CivetAuthHandler *handler);
  376. void
  377. addAuthHandler(const std::string &uri, CivetAuthHandler &handler)
  378. {
  379. addAuthHandler(uri, &handler);
  380. }
  381. /**
  382. * removeAuthHandler(const std::string &)
  383. *
  384. * Removes an authorization handler.
  385. *
  386. * @param uri - the exact URL used in addAuthHandler().
  387. */
  388. void removeAuthHandler(const std::string &uri);
  389. /**
  390. * getListeningPorts()
  391. *
  392. * Returns a list of ports that are listening
  393. *
  394. * @return A vector of ports
  395. */
  396. std::vector<int> getListeningPorts();
  397. /**
  398. * getListeningPorts()
  399. *
  400. * Variant of getListeningPorts() returning the full port information
  401. * (protocol, SSL, ...)
  402. *
  403. * @return A vector of ports
  404. */
  405. std::vector<struct mg_server_port> getListeningPortsFull();
  406. /**
  407. * getCookie(struct mg_connection *conn, const std::string &cookieName,
  408. * std::string &cookieValue)
  409. *
  410. * Puts the cookie value string that matches the cookie name in the
  411. * cookieValue destination string.
  412. *
  413. * @param conn - the connection information
  414. * @param cookieName - cookie name to get the value from
  415. * @param cookieValue - cookie value is returned using this reference
  416. * @returns the size of the cookie value string read.
  417. */
  418. static int getCookie(struct mg_connection *conn,
  419. const std::string &cookieName,
  420. std::string &cookieValue);
  421. /**
  422. * getHeader(struct mg_connection *conn, const std::string &headerName)
  423. * @param conn - the connection information
  424. * @param headerName - header name to get the value from
  425. * @returns a char array which contains the header value as string
  426. */
  427. static const char *getHeader(struct mg_connection *conn,
  428. const std::string &headerName);
  429. /**
  430. * getParam(struct mg_connection *conn, const char *, std::string &, size_t)
  431. *
  432. * Returns a query which contained in the supplied buffer. The
  433. * occurrence value is a zero-based index of a particular key name. This
  434. * should not be confused with the index over all of the keys. Note that
  435. *this
  436. * function assumes that parameters are sent as text in http query string
  437. * format, which is the default for web forms. This function will work for
  438. * html forms with method="GET" and method="POST" attributes. In other
  439. *cases,
  440. * you may use a getParam version that directly takes the data instead of
  441. *the
  442. * connection as a first argument.
  443. *
  444. * @param conn - parameters are read from the data sent through this
  445. *connection
  446. * @param name - the key to search for
  447. * @param dst - the destination string
  448. * @param occurrence - the occurrence of the selected name in the query (0
  449. *based).
  450. * @return true if key was found
  451. */
  452. static bool getParam(struct mg_connection *conn,
  453. const char *name,
  454. std::string &dst,
  455. size_t occurrence = 0);
  456. /**
  457. * getParam(const std::string &, const char *, std::string &, size_t)
  458. *
  459. * Returns a query parameter contained in the supplied buffer. The
  460. * occurrence value is a zero-based index of a particular key name. This
  461. * should not be confused with the index over all of the keys.
  462. *
  463. * @param data - the query string (text)
  464. * @param name - the key to search for
  465. * @param dst - the destination string
  466. * @param occurrence - the occurrence of the selected name in the query (0
  467. *based).
  468. * @return true if key was found
  469. */
  470. static bool
  471. getParam(const std::string &data,
  472. const char *name,
  473. std::string &dst,
  474. size_t occurrence = 0)
  475. {
  476. return getParam(data.c_str(), data.length(), name, dst, occurrence);
  477. }
  478. /**
  479. * getParam(const char *, size_t, const char *, std::string &, size_t)
  480. *
  481. * Returns a query parameter contained in the supplied buffer. The
  482. * occurrence value is a zero-based index of a particular key name. This
  483. * should not be confused with the index over all of the keys.
  484. *
  485. * @param data the - query string (text)
  486. * @param data_len - length of the query string
  487. * @param name - the key to search for
  488. * @param dst - the destination string
  489. * @param occurrence - the occurrence of the selected name in the query (0
  490. *based).
  491. * @return true if key was found
  492. */
  493. static bool getParam(const char *data,
  494. size_t data_len,
  495. const char *name,
  496. std::string &dst,
  497. size_t occurrence = 0);
  498. /**
  499. * getPostData(struct mg_connection *)
  500. *
  501. * Returns response body from a request made as POST. Since the
  502. * connections map is protected, it can't be directly accessed.
  503. * This uses string to store post data to handle big posts.
  504. *
  505. * @param conn - connection from which post data will be read
  506. * @return Post data (empty if not available).
  507. */
  508. static std::string getPostData(struct mg_connection *conn);
  509. /**
  510. * urlDecode(const std::string &, std::string &, bool)
  511. *
  512. * @param src - string to be decoded
  513. * @param dst - destination string
  514. * @param is_form_url_encoded - true if form url encoded
  515. * form-url-encoded data differs from URI encoding in a way that it
  516. * uses '+' as character for space, see RFC 1866 section 8.2.1
  517. * http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
  518. */
  519. static void
  520. urlDecode(const std::string &src,
  521. std::string &dst,
  522. bool is_form_url_encoded = true)
  523. {
  524. urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
  525. }
  526. /**
  527. * urlDecode(const char *, size_t, std::string &, bool)
  528. *
  529. * @param src - buffer to be decoded
  530. * @param src_len - length of buffer to be decoded
  531. * @param dst - destination string
  532. * @param is_form_url_encoded - true if form url encoded
  533. * form-url-encoded data differs from URI encoding in a way that it
  534. * uses '+' as character for space, see RFC 1866 section 8.2.1
  535. * http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
  536. */
  537. static void urlDecode(const char *src,
  538. size_t src_len,
  539. std::string &dst,
  540. bool is_form_url_encoded = true);
  541. /**
  542. * urlDecode(const char *, std::string &, bool)
  543. *
  544. * @param src - buffer to be decoded (0 terminated)
  545. * @param dst - destination string
  546. * @param is_form_url_encoded true - if form url encoded
  547. * form-url-encoded data differs from URI encoding in a way that it
  548. * uses '+' as character for space, see RFC 1866 section 8.2.1
  549. * http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
  550. */
  551. static void urlDecode(const char *src,
  552. std::string &dst,
  553. bool is_form_url_encoded = true);
  554. /**
  555. * urlEncode(const std::string &, std::string &, bool)
  556. *
  557. * @param src - buffer to be encoded
  558. * @param dst - destination string
  559. * @param append - true if string should not be cleared before encoding.
  560. */
  561. static void
  562. urlEncode(const std::string &src, std::string &dst, bool append = false)
  563. {
  564. urlEncode(src.c_str(), src.length(), dst, append);
  565. }
  566. /**
  567. * urlEncode(const char *, size_t, std::string &, bool)
  568. *
  569. * @param src - buffer to be encoded (0 terminated)
  570. * @param dst - destination string
  571. * @param append - true if string should not be cleared before encoding.
  572. */
  573. static void
  574. urlEncode(const char *src, std::string &dst, bool append = false);
  575. /**
  576. * urlEncode(const char *, size_t, std::string &, bool)
  577. *
  578. * @param src - buffer to be encoded
  579. * @param src_len - length of buffer to be decoded
  580. * @param dst - destination string
  581. * @param append - true if string should not be cleared before encoding.
  582. */
  583. static void urlEncode(const char *src,
  584. size_t src_len,
  585. std::string &dst,
  586. bool append = false);
  587. // generic user context which can be set/read,
  588. // the server does nothing with this apart from keep it.
  589. const void *
  590. getUserContext() const
  591. {
  592. return UserContext;
  593. }
  594. protected:
  595. class CivetConnection
  596. {
  597. public:
  598. std::vector<char> postData;
  599. };
  600. struct mg_context *context;
  601. std::map<const struct mg_connection *, CivetConnection> connections;
  602. // generic user context which can be set/read,
  603. // the server does nothing with this apart from keep it.
  604. const void *UserContext;
  605. private:
  606. /**
  607. * requestHandler(struct mg_connection *, void *cbdata)
  608. *
  609. * Handles the incoming request.
  610. *
  611. * @param conn - the connection information
  612. * @param cbdata - pointer to the CivetHandler instance.
  613. * @returns 0 if implemented, false otherwise
  614. */
  615. static int requestHandler(struct mg_connection *conn, void *cbdata);
  616. static int webSocketConnectionHandler(const struct mg_connection *conn,
  617. void *cbdata);
  618. static void webSocketReadyHandler(struct mg_connection *conn, void *cbdata);
  619. static int webSocketDataHandler(struct mg_connection *conn,
  620. int bits,
  621. char *data,
  622. size_t data_len,
  623. void *cbdata);
  624. static void webSocketCloseHandler(const struct mg_connection *conn,
  625. void *cbdata);
  626. /**
  627. * authHandler(struct mg_connection *, void *cbdata)
  628. *
  629. * Handles the authorization requests.
  630. *
  631. * @param conn - the connection information
  632. * @param cbdata - pointer to the CivetAuthHandler instance.
  633. * @returns 1 if authorized, 0 otherwise
  634. */
  635. static int authHandler(struct mg_connection *conn, void *cbdata);
  636. /**
  637. * closeHandler(struct mg_connection *)
  638. *
  639. * Handles closing a request (internal handler)
  640. *
  641. * @param conn - the connection information
  642. */
  643. static void closeHandler(const struct mg_connection *conn);
  644. /**
  645. * Stores the user provided close handler
  646. */
  647. void (*userCloseHandler)(const struct mg_connection *conn);
  648. };
  649. #endif /* __cplusplus */
  650. #endif /* CIVETSERVER_HEADER_INCLUDED */