1
0

HttpService.cpp 5.2 KB

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