HttpHandler.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #ifndef HTTP_HANDLER_H_
  2. #define HTTP_HANDLER_H_
  3. #include "HttpService.h"
  4. #include "HttpParser.h"
  5. #include "FileCache.h"
  6. /*
  7. <!DOCTYPE html>
  8. <html>
  9. <head>
  10. <title>404 Not Found</title>
  11. </head>
  12. <body>
  13. <center><h1>404 Not Found</h1></center>
  14. <hr>
  15. </body>
  16. </html>
  17. */
  18. static inline void make_http_status_page(http_status status_code, std::string& page) {
  19. char szCode[8];
  20. snprintf(szCode, sizeof(szCode), "%d ", status_code);
  21. const char* status_message = http_status_str(status_code);
  22. page += R"(<!DOCTYPE html>
  23. <html>
  24. <head>
  25. <title>)";
  26. page += szCode; page += status_message;
  27. page += R"(</title>
  28. </head>
  29. <body>
  30. <center><h1>)";
  31. page += szCode; page += status_message;
  32. page += R"(</h1></center>
  33. <hr>
  34. </body>
  35. </html>)";
  36. }
  37. class HttpHandler {
  38. public:
  39. HttpService* service;
  40. FileCache* files;
  41. char srcip[64];
  42. int srcport;
  43. HttpParser parser;
  44. HttpRequest req;
  45. HttpResponse res;
  46. file_cache_t* fc;
  47. HttpHandler() {
  48. service = NULL;
  49. files = NULL;
  50. init();
  51. }
  52. void init() {
  53. parser.parser_request_init(&req);
  54. req.init();
  55. res.init();
  56. fc = NULL;
  57. }
  58. int handle_request() {
  59. // preprocessor -> api -> web -> postprocessor
  60. // preprocessor
  61. if (service->preprocessor) {
  62. if (service->preprocessor(&req, &res) == HANDLE_DONE) {
  63. return HANDLE_DONE;
  64. }
  65. }
  66. http_api_handler api = NULL;
  67. int ret = service->GetApi(req.url.c_str(), req.method, &api);
  68. if (api) {
  69. // api service
  70. if (api(&req, &res) == HANDLE_DONE) {
  71. return HANDLE_DONE;
  72. }
  73. }
  74. else if (ret == HTTP_STATUS_METHOD_NOT_ALLOWED) {
  75. // Method Not Allowed
  76. res.status_code = HTTP_STATUS_METHOD_NOT_ALLOWED;
  77. }
  78. else if (req.method == HTTP_GET) {
  79. // web service
  80. std::string filepath = service->document_root;
  81. filepath += req.url.c_str();
  82. if (strcmp(req.url.c_str(), "/") == 0) {
  83. filepath += service->home_page;
  84. }
  85. fc = files->Open(filepath.c_str());
  86. // Not Found
  87. if (fc == NULL) {
  88. res.status_code = HTTP_STATUS_NOT_FOUND;
  89. }
  90. else {
  91. // Not Modified
  92. auto iter = req.headers.find("if-not-match");
  93. if (iter != req.headers.end() &&
  94. strcmp(iter->second.c_str(), fc->etag) == 0) {
  95. res.status_code = HTTP_STATUS_NOT_MODIFIED;
  96. fc = NULL;
  97. }
  98. else {
  99. iter = req.headers.find("if-modified-since");
  100. if (iter != req.headers.end() &&
  101. strcmp(iter->second.c_str(), fc->last_modified) == 0) {
  102. res.status_code = HTTP_STATUS_NOT_MODIFIED;
  103. fc = NULL;
  104. }
  105. }
  106. }
  107. }
  108. else {
  109. // Not Implemented
  110. res.status_code = HTTP_STATUS_NOT_IMPLEMENTED;
  111. }
  112. // html page
  113. if (res.status_code >= 400 && res.body.size() == 0) {
  114. // error page
  115. if (service->error_page.size() != 0) {
  116. std::string filepath = service->document_root;
  117. filepath += '/';
  118. filepath += service->error_page;
  119. fc = files->Open(filepath.c_str());
  120. }
  121. // status page
  122. if (fc == NULL && res.body.size() == 0) {
  123. res.content_type = TEXT_HTML;
  124. make_http_status_page(res.status_code, res.body);
  125. }
  126. }
  127. // file
  128. if (fc) {
  129. if (fc->content_type && *fc->content_type != '\0') {
  130. res.headers["Content-Type"] = fc->content_type;
  131. }
  132. res.headers["Content-Length"] = std::to_string(fc->filebuf.len);
  133. res.headers["Last-Modified"] = fc->last_modified;
  134. res.headers["Etag"] = fc->etag;
  135. }
  136. // postprocessor
  137. if (service->postprocessor) {
  138. if (service->postprocessor(&req, &res) == HANDLE_DONE) {
  139. return HANDLE_DONE;
  140. }
  141. }
  142. return HANDLE_DONE;
  143. }
  144. };
  145. #endif // HTTP_HANDLER_H_