HttpHandler.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include "HttpHandler.h"
  2. #include "hbase.h"
  3. #include "hstring.h"
  4. #include "http_page.h"
  5. int HttpHandler::HandleRequest() {
  6. // preprocessor -> api -> web -> postprocessor
  7. // preprocessor
  8. req.ParseUrl();
  9. if (service->preprocessor) {
  10. if (service->preprocessor(&req, &res) == HANDLE_DONE) {
  11. return HANDLE_DONE;
  12. }
  13. }
  14. http_api_handler api = NULL;
  15. int ret = 0;
  16. if (service->api_handlers.size() != 0) {
  17. ret = service->GetApi(&req, &api);
  18. }
  19. if (api) {
  20. // api service
  21. if (api(&req, &res) == HANDLE_DONE) {
  22. return HANDLE_DONE;
  23. }
  24. }
  25. else if (ret == HTTP_STATUS_METHOD_NOT_ALLOWED) {
  26. // Method Not Allowed
  27. res.status_code = HTTP_STATUS_METHOD_NOT_ALLOWED;
  28. }
  29. else if (service->document_root.size() != 0 && req.method == HTTP_GET) {
  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. fc = files->Open(filepath.c_str(), (void*)req_path);
  49. }
  50. if (fc == NULL) {
  51. // Not Found
  52. res.status_code = HTTP_STATUS_NOT_FOUND;
  53. }
  54. else {
  55. // Not Modified
  56. auto iter = req.headers.find("if-not-match");
  57. if (iter != req.headers.end() &&
  58. strcmp(iter->second.c_str(), fc->etag) == 0) {
  59. res.status_code = HTTP_STATUS_NOT_MODIFIED;
  60. fc = NULL;
  61. }
  62. else {
  63. iter = req.headers.find("if-modified-since");
  64. if (iter != req.headers.end() &&
  65. strcmp(iter->second.c_str(), fc->last_modified) == 0) {
  66. res.status_code = HTTP_STATUS_NOT_MODIFIED;
  67. fc = NULL;
  68. }
  69. }
  70. }
  71. }
  72. else {
  73. // Not Implemented
  74. res.status_code = HTTP_STATUS_NOT_IMPLEMENTED;
  75. }
  76. make_http_status_page:
  77. // html page
  78. if (res.status_code >= 400 && res.body.size() == 0) {
  79. // error page
  80. if (service->error_page.size() != 0) {
  81. std::string filepath = service->document_root;
  82. filepath += '/';
  83. filepath += service->error_page;
  84. fc = files->Open(filepath.c_str(), NULL);
  85. }
  86. // status page
  87. if (fc == NULL && res.body.size() == 0) {
  88. res.content_type = TEXT_HTML;
  89. make_http_status_page(res.status_code, res.body);
  90. }
  91. }
  92. // file
  93. if (fc) {
  94. res.content = (unsigned char*)fc->filebuf.base;
  95. res.content_length = fc->filebuf.len;
  96. if (fc->content_type && *fc->content_type != '\0') {
  97. res.headers["Content-Type"] = fc->content_type;
  98. res.FillContentType();
  99. }
  100. res.headers["Content-Length"] = asprintf("%d", res.content_length);
  101. res.headers["Last-Modified"] = fc->last_modified;
  102. res.headers["Etag"] = fc->etag;
  103. }
  104. // postprocessor
  105. if (service->postprocessor) {
  106. if (service->postprocessor(&req, &res) == HANDLE_DONE) {
  107. return HANDLE_DONE;
  108. }
  109. }
  110. return HANDLE_DONE;
  111. }