1
0

HttpHandler.cpp 3.7 KB

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