CivetServer.h 21 KB

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