HttpHandler.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include "HttpHandler.h"
  2. #include "hbase.h"
  3. #include "http_page.h"
  4. int HttpHandler::HandleRequest() {
  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 && req.method == HTTP_GET) {
  29. // web service
  30. // path safe check
  31. const char* req_path = req.path.c_str();
  32. if (*req_path != '/' || strstr(req_path, "/../")) {
  33. res.status_code = HTTP_STATUS_BAD_REQUEST;
  34. goto make_http_status_page;
  35. }
  36. std::string filepath = service->document_root;
  37. filepath += req_path;
  38. if (req_path[1] == '\0') {
  39. filepath += service->home_page;
  40. }
  41. bool is_dir = filepath.c_str()[filepath.size()-1] == '/';
  42. bool is_index_of = false;
  43. if (service->index_of.size() != 0 && strstartswith(req_path, service->index_of.c_str())) {
  44. is_index_of = true;
  45. }
  46. if (!is_dir || is_index_of) {
  47. fc = files->Open(filepath.c_str(), (void*)req_path);
  48. }
  49. if (fc == NULL) {
  50. // Not Found
  51. ret = HTTP_STATUS_NOT_FOUND;
  52. }
  53. else {
  54. // Not Modified
  55. auto iter = req.headers.find("if-not-match");
  56. if (iter != req.headers.end() &&
  57. strcmp(iter->second.c_str(), fc->etag) == 0) {
  58. ret = HTTP_STATUS_NOT_MODIFIED;
  59. fc = NULL;
  60. }
  61. else {
  62. iter = req.headers.find("if-modified-since");
  63. if (iter != req.headers.end() &&
  64. strcmp(iter->second.c_str(), fc->last_modified) == 0) {
  65. ret = HTTP_STATUS_NOT_MODIFIED;
  66. fc = NULL;
  67. }
  68. }
  69. }
  70. }
  71. else {
  72. // Not Implemented
  73. ret = HTTP_STATUS_NOT_IMPLEMENTED;
  74. }
  75. make_http_status_page:
  76. if (ret >= 100 && ret < 600) {
  77. res.status_code = (http_status)ret;
  78. }
  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. if (fc) {
  94. // link file cache
  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. ret = service->postprocessor(&req, &res);
  110. }
  111. return ret;
  112. }