HttpHandler.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #include "HttpHandler.h"
  2. #include "hbase.h"
  3. #include "http_page.h"
  4. int HttpHandler::HandleHttpRequest() {
  5. // preprocessor -> api -> web -> postprocessor
  6. int ret = 0;
  7. http_api_handler api = NULL;
  8. req.ParseUrl();
  9. req.client_addr.ip = ip;
  10. req.client_addr.port = port;
  11. preprocessor:
  12. if (service->preprocessor) {
  13. ret = service->preprocessor(&req, &res);
  14. if (ret != 0) {
  15. goto make_http_status_page;
  16. }
  17. }
  18. if (service->api_handlers.size() != 0) {
  19. service->GetApi(&req, &api);
  20. }
  21. if (api) {
  22. // api service
  23. ret = api(&req, &res);
  24. if (ret != 0) {
  25. goto make_http_status_page;
  26. }
  27. }
  28. else if (service->document_root.size() != 0 &&
  29. (req.method == HTTP_GET || req.method == HTTP_HEAD)) {
  30. // web service
  31. // path safe check
  32. const char* req_path = req.path.c_str();
  33. if (*req_path != '/' || strstr(req_path, "/../")) {
  34. res.status_code = HTTP_STATUS_BAD_REQUEST;
  35. goto make_http_status_page;
  36. }
  37. std::string filepath = service->document_root;
  38. filepath += req_path;
  39. if (req_path[1] == '\0') {
  40. filepath += service->home_page;
  41. }
  42. bool is_dir = filepath.c_str()[filepath.size()-1] == '/';
  43. bool is_index_of = false;
  44. if (service->index_of.size() != 0 && strstartswith(req_path, service->index_of.c_str())) {
  45. is_index_of = true;
  46. }
  47. if (!is_dir || is_index_of) {
  48. bool need_read = req.method == HTTP_HEAD ? false : true;
  49. fc = files->Open(filepath.c_str(), need_read, (void*)req_path);
  50. }
  51. if (fc == NULL) {
  52. // Not Found
  53. ret = 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. ret = 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. ret = HTTP_STATUS_NOT_MODIFIED;
  68. fc = NULL;
  69. }
  70. }
  71. }
  72. }
  73. else {
  74. // Not Implemented
  75. ret = HTTP_STATUS_NOT_IMPLEMENTED;
  76. }
  77. make_http_status_page:
  78. if (ret >= 100 && ret < 600) {
  79. res.status_code = (http_status)ret;
  80. }
  81. if (res.status_code >= 400 && res.body.size() == 0) {
  82. // error page
  83. if (service->error_page.size() != 0) {
  84. std::string filepath = service->document_root;
  85. filepath += '/';
  86. filepath += service->error_page;
  87. fc = files->Open(filepath.c_str(), true, NULL);
  88. }
  89. // status page
  90. if (fc == NULL && res.body.size() == 0) {
  91. res.content_type = TEXT_HTML;
  92. make_http_status_page(res.status_code, res.body);
  93. }
  94. }
  95. if (fc) {
  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. }
  100. res.headers["Last-Modified"] = fc->last_modified;
  101. res.headers["Etag"] = fc->etag;
  102. if (req.method == HTTP_HEAD) {
  103. res.headers["Accept-Ranges"] = "bytes";
  104. res.content = NULL;
  105. fc = NULL;
  106. } else {
  107. res.content = fc->filebuf.base;
  108. }
  109. }
  110. postprocessor:
  111. if (service->postprocessor) {
  112. ret = service->postprocessor(&req, &res);
  113. }
  114. return ret;
  115. }