embedded_cpp.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /* Copyright (c) 2013-2017 the Civetweb developers
  2. * Copyright (c) 2013 No Face Press, LLC
  3. * License http://opensource.org/licenses/mit-license.php MIT License
  4. */
  5. // Simple example program on how to use Embedded C++ interface.
  6. #include "CivetServer.h"
  7. #include <cstring>
  8. #ifdef _WIN32
  9. #include <windows.h>
  10. #else
  11. #include <unistd.h>
  12. #endif
  13. #define DOCUMENT_ROOT "."
  14. #define PORT "8081"
  15. #define EXAMPLE_URI "/example"
  16. #define EXIT_URI "/exit"
  17. bool exitNow = false;
  18. class ExampleHandler : public CivetHandler
  19. {
  20. public:
  21. bool
  22. handleGet(CivetServer *server, struct mg_connection *conn)
  23. {
  24. mg_printf(conn,
  25. "HTTP/1.1 200 OK\r\nContent-Type: "
  26. "text/html\r\nConnection: close\r\n\r\n");
  27. mg_printf(conn, "<html><body>\r\n");
  28. mg_printf(conn,
  29. "<h2>This is an example text from a C++ handler</h2>\r\n");
  30. mg_printf(conn,
  31. "<p>To see a page from the A handler <a "
  32. "href=\"a\">click here</a></p>\r\n");
  33. mg_printf(conn,
  34. "<p>To see a page from the A handler with a parameter "
  35. "<a href=\"a?param=1\">click here</a></p>\r\n");
  36. mg_printf(conn,
  37. "<p>To see a page from the A/B handler <a "
  38. "href=\"a/b\">click here</a></p>\r\n");
  39. mg_printf(conn,
  40. "<p>To see a page from the *.foo handler <a "
  41. "href=\"xy.foo\">click here</a></p>\r\n");
  42. mg_printf(conn,
  43. "<p>To exit <a href=\"%s\">click here</a></p>\r\n",
  44. EXIT_URI);
  45. mg_printf(conn, "</body></html>\r\n");
  46. return true;
  47. }
  48. };
  49. class ExitHandler : public CivetHandler
  50. {
  51. public:
  52. bool
  53. handleGet(CivetServer *server, struct mg_connection *conn)
  54. {
  55. mg_printf(conn,
  56. "HTTP/1.1 200 OK\r\nContent-Type: "
  57. "text/plain\r\nConnection: close\r\n\r\n");
  58. mg_printf(conn, "Bye!\n");
  59. exitNow = true;
  60. return true;
  61. }
  62. };
  63. class AHandler : public CivetHandler
  64. {
  65. private:
  66. bool
  67. handleAll(const char *method,
  68. CivetServer *server,
  69. struct mg_connection *conn)
  70. {
  71. std::string s = "";
  72. mg_printf(conn,
  73. "HTTP/1.1 200 OK\r\nContent-Type: "
  74. "text/html\r\nConnection: close\r\n\r\n");
  75. mg_printf(conn, "<html><body>");
  76. mg_printf(conn, "<h2>This is the A handler for \"%s\" !</h2>", method);
  77. if (CivetServer::getParam(conn, "param", s)) {
  78. mg_printf(conn, "<p>param set to %s</p>", s.c_str());
  79. } else {
  80. mg_printf(conn, "<p>param not set</p>");
  81. }
  82. mg_printf(conn, "</body></html>\n");
  83. return true;
  84. }
  85. public:
  86. bool
  87. handleGet(CivetServer *server, struct mg_connection *conn)
  88. {
  89. return handleAll("GET", server, conn);
  90. }
  91. bool
  92. handlePost(CivetServer *server, struct mg_connection *conn)
  93. {
  94. return handleAll("POST", server, conn);
  95. }
  96. };
  97. class ABHandler : public CivetHandler
  98. {
  99. public:
  100. bool
  101. handleGet(CivetServer *server, struct mg_connection *conn)
  102. {
  103. mg_printf(conn,
  104. "HTTP/1.1 200 OK\r\nContent-Type: "
  105. "text/html\r\nConnection: close\r\n\r\n");
  106. mg_printf(conn, "<html><body>");
  107. mg_printf(conn, "<h2>This is the AB handler!!!</h2>");
  108. mg_printf(conn, "</body></html>\n");
  109. return true;
  110. }
  111. };
  112. class FooHandler : public CivetHandler
  113. {
  114. public:
  115. bool
  116. handleGet(CivetServer *server, struct mg_connection *conn)
  117. {
  118. /* Handler may access the request info using mg_get_request_info */
  119. const struct mg_request_info *req_info = mg_get_request_info(conn);
  120. mg_printf(conn,
  121. "HTTP/1.1 200 OK\r\nContent-Type: "
  122. "text/html\r\nConnection: close\r\n\r\n");
  123. mg_printf(conn, "<html><body>\n");
  124. mg_printf(conn, "<h2>This is the Foo GET handler!!!</h2>\n");
  125. mg_printf(conn,
  126. "<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n",
  127. req_info->request_method,
  128. req_info->request_uri,
  129. req_info->http_version);
  130. mg_printf(conn, "</body></html>\n");
  131. return true;
  132. }
  133. bool
  134. handlePost(CivetServer *server, struct mg_connection *conn)
  135. {
  136. /* Handler may access the request info using mg_get_request_info */
  137. const struct mg_request_info *req_info = mg_get_request_info(conn);
  138. long long rlen, wlen;
  139. long long nlen = 0;
  140. long long tlen = req_info->content_length;
  141. char buf[1024];
  142. mg_printf(conn,
  143. "HTTP/1.1 200 OK\r\nContent-Type: "
  144. "text/html\r\nConnection: close\r\n\r\n");
  145. mg_printf(conn, "<html><body>\n");
  146. mg_printf(conn, "<h2>This is the Foo POST handler!!!</h2>\n");
  147. mg_printf(conn,
  148. "<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n",
  149. req_info->request_method,
  150. req_info->request_uri,
  151. req_info->http_version);
  152. mg_printf(conn, "<p>Content Length: %li</p>\n", (long)tlen);
  153. mg_printf(conn, "<pre>\n");
  154. while (nlen < tlen) {
  155. rlen = tlen - nlen;
  156. if (rlen > sizeof(buf)) {
  157. rlen = sizeof(buf);
  158. }
  159. rlen = mg_read(conn, buf, (size_t)rlen);
  160. if (rlen <= 0) {
  161. break;
  162. }
  163. wlen = mg_write(conn, buf, (size_t)rlen);
  164. if (rlen != rlen) {
  165. break;
  166. }
  167. nlen += wlen;
  168. }
  169. mg_printf(conn, "\n</pre>\n");
  170. mg_printf(conn, "</body></html>\n");
  171. return true;
  172. }
  173. #define fopen_recursive fopen
  174. bool
  175. handlePut(CivetServer *server, struct mg_connection *conn)
  176. {
  177. /* Handler may access the request info using mg_get_request_info */
  178. const struct mg_request_info *req_info = mg_get_request_info(conn);
  179. long long rlen, wlen;
  180. long long nlen = 0;
  181. long long tlen = req_info->content_length;
  182. FILE * f;
  183. char buf[1024];
  184. int fail = 0;
  185. #ifdef _WIN32
  186. _snprintf(buf, sizeof(buf), "D:\\somewhere\\%s\\%s", req_info->remote_user, req_info->local_uri);
  187. buf[sizeof(buf)-1] = 0;
  188. if (strlen(buf)>255) {
  189. /* Windows will not work with path > 260 (MAX_PATH), unless we use
  190. * the unicode API. However, this is just an example code: A real
  191. * code will probably never store anything to D:\\somewhere and
  192. * must be adapted to the specific needs anyhow. */
  193. fail = 1;
  194. f = NULL;
  195. } else {
  196. f = fopen_recursive(buf, "wb");
  197. }
  198. #else
  199. snprintf(buf, sizeof(buf), "~/somewhere/%s/%s", req_info->remote_user, req_info->local_uri);
  200. buf[sizeof(buf)-1] = 0;
  201. if (strlen(buf)>1020) {
  202. /* The string is too long and probably truncated. Make sure an
  203. * UTF-8 string is never truncated between the UTF-8 code bytes.
  204. * This example code must be adapted to the specific needs. */
  205. fail = 1;
  206. f = NULL;
  207. } else {
  208. f = fopen_recursive(buf, "w");
  209. }
  210. #endif
  211. if (!f) {
  212. fail = 1;
  213. } else {
  214. while (nlen < tlen) {
  215. rlen = tlen - nlen;
  216. if (rlen > sizeof(buf)) {
  217. rlen = sizeof(buf);
  218. }
  219. rlen = mg_read(conn, buf, (size_t)rlen);
  220. if (rlen <= 0) {
  221. fail = 1;
  222. break;
  223. }
  224. wlen = fwrite(buf, 1, (size_t)rlen, f);
  225. if (rlen != rlen) {
  226. fail = 1;
  227. break;
  228. }
  229. nlen += wlen;
  230. }
  231. fclose(f);
  232. }
  233. if (fail) {
  234. mg_printf(conn,
  235. "HTTP/1.1 409 Conflict\r\n"
  236. "Content-Type: text/plain\r\n"
  237. "Connection: close\r\n\r\n");
  238. } else {
  239. mg_printf(conn,
  240. "HTTP/1.1 201 Created\r\n"
  241. "Content-Type: text/plain\r\n"
  242. "Connection: close\r\n\r\n");
  243. }
  244. return true;
  245. }
  246. };
  247. int
  248. main(int argc, char *argv[])
  249. {
  250. const char *options[] = {
  251. "document_root", DOCUMENT_ROOT, "listening_ports", PORT, 0};
  252. std::vector<std::string> cpp_options;
  253. for (int i=0; i<(sizeof(options)/sizeof(options[0])-1); i++) {
  254. cpp_options.push_back(options[i]);
  255. }
  256. // CivetServer server(options); // <-- C style start
  257. CivetServer server(cpp_options); // <-- C++ style start
  258. ExampleHandler h_ex;
  259. server.addHandler(EXAMPLE_URI, h_ex);
  260. ExitHandler h_exit;
  261. server.addHandler(EXIT_URI, h_exit);
  262. AHandler h_a;
  263. server.addHandler("/a", h_a);
  264. ABHandler h_ab;
  265. server.addHandler("/a/b", h_ab);
  266. FooHandler h_foo;
  267. server.addHandler("", h_foo);
  268. printf("Browse files at http://localhost:%s/\n", PORT);
  269. printf("Run example at http://localhost:%s%s\n", PORT, EXAMPLE_URI);
  270. printf("Exit at http://localhost:%s%s\n", PORT, EXIT_URI);
  271. while (!exitNow) {
  272. #ifdef _WIN32
  273. Sleep(1000);
  274. #else
  275. sleep(1);
  276. #endif
  277. }
  278. printf("Bye!\n");
  279. return 0;
  280. }