HttpHandler.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #include "HttpHandler.h"
  2. #include "hbase.h"
  3. #include "http_page.h"
  4. int HttpHandler::HandleRequest() {
  5. // preprocessor -> api -> web -> postprocessor
  6. // preprocessor
  7. req.ParseUrl();
  8. req.client_addr.ip = ip;
  9. req.client_addr.port = port;
  10. if (service->preprocessor) {
  11. if (service->preprocessor(&req, &res) == HANDLE_DONE) {
  12. return HANDLE_DONE;
  13. }
  14. }
  15. http_api_handler api = NULL;
  16. int ret = 0;
  17. if (service->api_handlers.size() != 0) {
  18. ret = service->GetApi(&req, &api);
  19. }
  20. if (api) {
  21. // api service
  22. if (api(&req, &res) == HANDLE_DONE) {
  23. return HANDLE_DONE;
  24. }
  25. }
  26. else if (ret == HTTP_STATUS_METHOD_NOT_ALLOWED) {
  27. // Method Not Allowed
  28. res.status_code = HTTP_STATUS_METHOD_NOT_ALLOWED;
  29. }
  30. else if (service->document_root.size() != 0 && req.method == HTTP_GET) {
  31. // web service
  32. // path safe check
  33. const char* req_path = req.path.c_str();
  34. if (*req_path != '/' || strstr(req_path, "/../")) {
  35. res.status_code = HTTP_STATUS_BAD_REQUEST;
  36. goto make_http_status_page;
  37. }
  38. std::string filepath = service->document_root;
  39. filepath += req_path;
  40. if (req_path[1] == '\0') {
  41. filepath += service->home_page;
  42. }
  43. bool is_dir = filepath.c_str()[filepath.size()-1] == '/';
  44. bool is_index_of = false;
  45. if (service->index_of.size() != 0 && strstartswith(req_path, service->index_of.c_str())) {
  46. is_index_of = true;
  47. }
  48. if (!is_dir || is_index_of) {
  49. fc = files->Open(filepath.c_str(), (void*)req_path);
  50. }
  51. if (fc == NULL) {
  52. // Not Found
  53. res.status_code = HTTP_STATUS_NOT_FOUND;
  54. }
  55. else {
  56. // Not Modified
  57. auto iter = req.headers.find("if-not-match");
  58. if (iter != req.headers.end() &&
  59. strcmp(iter->second.c_str(), fc->etag) == 0) {
  60. res.status_code = HTTP_STATUS_NOT_MODIFIED;
  61. fc = NULL;
  62. }
  63. else {
  64. iter = req.headers.find("if-modified-since");
  65. if (iter != req.headers.end() &&
  66. strcmp(iter->second.c_str(), fc->last_modified) == 0) {
  67. res.status_code = HTTP_STATUS_NOT_MODIFIED;
  68. fc = NULL;
  69. }
  70. }
  71. }
  72. }
  73. else {
  74. // Not Implemented
  75. res.status_code = HTTP_STATUS_NOT_IMPLEMENTED;
  76. }
  77. make_http_status_page:
  78. // html page
  79. if (res.status_code >= 400 && res.body.size() == 0) {
  80. // error page
  81. if (service->error_page.size() != 0) {
  82. std::string filepath = service->document_root;
  83. filepath += '/';
  84. filepath += service->error_page;
  85. fc = files->Open(filepath.c_str(), NULL);
  86. }
  87. // status page
  88. if (fc == NULL && res.body.size() == 0) {
  89. res.content_type = TEXT_HTML;
  90. make_http_status_page(res.status_code, res.body);
  91. }
  92. }
  93. // file
  94. if (fc) {
  95. res.content = (unsigned char*)fc->filebuf.base;
  96. res.content_length = fc->filebuf.len;
  97. if (fc->content_type && *fc->content_type != '\0') {
  98. res.headers["Content-Type"] = fc->content_type;
  99. res.FillContentType();
  100. }
  101. char sz[64];
  102. snprintf(sz, sizeof(sz), "%d", res.content_length);
  103. res.headers["Content-Length"] = sz;
  104. res.headers["Last-Modified"] = fc->last_modified;
  105. res.headers["Etag"] = fc->etag;
  106. }
  107. // postprocessor
  108. if (service->postprocessor) {
  109. if (service->postprocessor(&req, &res) == HANDLE_DONE) {
  110. return HANDLE_DONE;
  111. }
  112. }
  113. return HANDLE_DONE;
  114. }