HttpService.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "HttpService.h"
  2. #include "HttpMiddleware.h"
  3. #include "hbase.h" // import hv_strendswith
  4. namespace hv {
  5. void HttpService::AddRoute(const char* path, http_method method, const http_handler& handler) {
  6. std::shared_ptr<http_method_handlers> method_handlers = NULL;
  7. auto iter = pathHandlers.find(path);
  8. if (iter == pathHandlers.end()) {
  9. // add path
  10. method_handlers = std::make_shared<http_method_handlers>();
  11. pathHandlers[path] = method_handlers;
  12. }
  13. else {
  14. method_handlers = iter->second;
  15. }
  16. for (auto iter = method_handlers->begin(); iter != method_handlers->end(); ++iter) {
  17. if (iter->method == method) {
  18. // update
  19. iter->handler = handler;
  20. return;
  21. }
  22. }
  23. // add
  24. method_handlers->push_back(http_method_handler(method, handler));
  25. }
  26. int HttpService::GetRoute(const char* url, http_method method, http_handler** handler) {
  27. // {base_url}/path?query
  28. const char* s = url;
  29. const char* b = base_url.c_str();
  30. while (*s && *b && *s == *b) {++s;++b;}
  31. if (*b != '\0') {
  32. return HTTP_STATUS_NOT_FOUND;
  33. }
  34. const char* e = s;
  35. while (*e && *e != '?') ++e;
  36. std::string path = std::string(s, e);
  37. auto iter = pathHandlers.find(path);
  38. if (iter == pathHandlers.end()) {
  39. if (handler) *handler = NULL;
  40. return HTTP_STATUS_NOT_FOUND;
  41. }
  42. auto method_handlers = iter->second;
  43. for (auto iter = method_handlers->begin(); iter != method_handlers->end(); ++iter) {
  44. if (iter->method == method) {
  45. if (handler) *handler = &iter->handler;
  46. return 0;
  47. }
  48. }
  49. if (handler) *handler = NULL;
  50. return HTTP_STATUS_METHOD_NOT_ALLOWED;
  51. }
  52. int HttpService::GetRoute(HttpRequest* req, http_handler** handler) {
  53. // {base_url}/path?query
  54. const char* s = req->path.c_str();
  55. const char* b = base_url.c_str();
  56. while (*s && *b && *s == *b) {++s;++b;}
  57. if (*b != '\0') {
  58. return HTTP_STATUS_NOT_FOUND;
  59. }
  60. const char* e = s;
  61. while (*e && *e != '?') ++e;
  62. std::string path = std::string(s, e);
  63. const char *kp, *ks, *vp, *vs;
  64. bool match;
  65. for (auto iter = pathHandlers.begin(); iter != pathHandlers.end(); ++iter) {
  66. kp = iter->first.c_str();
  67. vp = path.c_str();
  68. match = false;
  69. std::map<std::string, std::string> params;
  70. while (*kp && *vp) {
  71. if (kp[0] == '*') {
  72. // wildcard *
  73. match = hv_strendswith(vp, kp+1);
  74. break;
  75. } else if (*kp != *vp) {
  76. match = false;
  77. break;
  78. } else if (kp[0] == '/' && (kp[1] == ':' || kp[1] == '{')) {
  79. // RESTful /:field/
  80. // RESTful /{field}/
  81. kp += 2;
  82. ks = kp;
  83. while (*kp && *kp != '/') {++kp;}
  84. vp += 1;
  85. vs = vp;
  86. while (*vp && *vp != '/') {++vp;}
  87. int klen = kp - ks;
  88. if (*(ks-1) == '{' && *(kp-1) == '}') {
  89. --klen;
  90. }
  91. params[std::string(ks, klen)] = std::string(vs, vp-vs);
  92. continue;
  93. } else {
  94. ++kp;
  95. ++vp;
  96. }
  97. }
  98. match = match ? match : (*kp == '\0' && *vp == '\0');
  99. if (match) {
  100. auto method_handlers = iter->second;
  101. for (auto iter = method_handlers->begin(); iter != method_handlers->end(); ++iter) {
  102. if (iter->method == req->method) {
  103. for (auto& param : params) {
  104. // RESTful /:field/ => req->query_params[field]
  105. req->query_params[param.first] = param.second;
  106. }
  107. if (handler) *handler = &iter->handler;
  108. return 0;
  109. }
  110. }
  111. if (params.size() == 0) {
  112. if (handler) *handler = NULL;
  113. return HTTP_STATUS_METHOD_NOT_ALLOWED;
  114. }
  115. }
  116. }
  117. if (handler) *handler = NULL;
  118. return HTTP_STATUS_NOT_FOUND;
  119. }
  120. void HttpService::Static(const char* path, const char* dir) {
  121. std::string strPath(path);
  122. if (strPath.back() != '/') strPath += '/';
  123. std::string strDir(dir);
  124. if (strDir.back() == '/') strDir.pop_back();
  125. staticDirs[strPath] = strDir;
  126. }
  127. std::string HttpService::GetStaticFilepath(const char* path) {
  128. std::string filepath;
  129. for (auto iter = staticDirs.begin(); iter != staticDirs.end(); ++iter) {
  130. if (hv_strstartswith(path, iter->first.c_str())) {
  131. filepath = iter->second + (path + iter->first.length() - 1);
  132. break;
  133. }
  134. }
  135. if (filepath.empty()) {
  136. return filepath;
  137. }
  138. if (filepath.back() == '/') {
  139. filepath += home_page;
  140. }
  141. return filepath;
  142. }
  143. void HttpService::Proxy(const char* path, const char* url) {
  144. proxies[path] = url;
  145. }
  146. std::string HttpService::GetProxyUrl(const char* path) {
  147. std::string url;
  148. for (auto iter = proxies.begin(); iter != proxies.end(); ++iter) {
  149. if (hv_strstartswith(path, iter->first.c_str())) {
  150. url = iter->second + (path + iter->first.length());
  151. break;
  152. }
  153. }
  154. return url;
  155. }
  156. void HttpService::AllowCORS() {
  157. Use(HttpMiddleware::CORS);
  158. }
  159. }