common.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include "kbf/http/common.h"
  2. #include <regex>
  3. #include <utility>
  4. #include <esp_log.h>
  5. #include <esp_http_server.h>
  6. #include "kbf/macros.h"
  7. using namespace kbf;
  8. void http::HTTPObject::parseToMap(map<string, string> &target, const string &buffer) {
  9. auto queryString = string(buffer);
  10. std::regex regex("([\\w]+)=([\\w]+)");
  11. std::smatch submatch;
  12. while (std::regex_search(queryString, submatch, regex)) {
  13. ESP_LOGD(TAG, " parsed: %s = %s", submatch[1].str().c_str(), submatch[2].str().c_str());
  14. target[submatch[1]] = submatch[2];
  15. queryString = submatch.suffix();
  16. }
  17. }
  18. http::Request::Request(httpd_req_t *httpdRequest) {
  19. this->httpdRequest = httpdRequest;
  20. method = static_cast<Method>(httpdRequest->method);
  21. uri = httpdRequest->uri;
  22. for (const auto &name : acceptedHeaders) {
  23. readHeader(name);
  24. }
  25. readQuery();
  26. readBody();
  27. }
  28. string http::Request::readHeader(const string &header) {
  29. auto len = httpd_req_get_hdr_value_len(httpdRequest, header.c_str());
  30. if (len == 0) {
  31. ESP_LOGD(TAG, " header not found: %s", header.c_str());
  32. return "";
  33. }
  34. char buffer[len + 1];
  35. CHECK(httpd_req_get_hdr_value_str(httpdRequest, header.c_str(), buffer, len + 1));
  36. ESP_LOGD(TAG, " found header: %s: %s", header.c_str(), buffer);
  37. headers[header] = buffer;
  38. return buffer;
  39. }
  40. void http::Request::readQuery() {
  41. auto queryLen = httpd_req_get_url_query_len(httpdRequest);
  42. char buffer[queryLen + 1];
  43. auto err = httpd_req_get_url_query_str(httpdRequest, buffer, queryLen + 1);
  44. if (err == ESP_ERR_NOT_FOUND) {
  45. ESP_LOGD(TAG, "no query found");
  46. return;
  47. } else
  48. CHECK(err);
  49. ESP_LOGD(TAG, "found query: %s", buffer);
  50. parseToMap(query, buffer);
  51. }
  52. void http::Request::readBody() {
  53. if (httpdRequest->content_len == 0) {
  54. return;
  55. }
  56. ESP_LOGD(TAG, "reading body, length = %d", httpdRequest->content_len);
  57. // TODO check if we have enough memory for the content!
  58. char buffer[httpdRequest->content_len];
  59. for (int i = 1; i <= MAX_READ_RETRY; i++) {
  60. int ret;
  61. if ((ret = httpd_req_recv(httpdRequest, buffer, httpdRequest->content_len)) <= 0) {
  62. if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
  63. if (i == MAX_READ_RETRY) {
  64. ESP_LOGE(TAG, "socket timeout, giving up");
  65. break;
  66. }
  67. ESP_LOGW(TAG, "socket timeout, retrying (attempt %d)", i);
  68. continue;
  69. }
  70. ESP_LOGE(TAG, "socket read failed: %d (%s)", ret, esp_err_to_name(ret));
  71. } else {
  72. body = string(buffer, httpdRequest->content_len);
  73. ESP_LOGD(TAG, " read: \"%s\"", body.c_str());
  74. parseToMap(postData, body);
  75. break;
  76. }
  77. }
  78. }
  79. http::Response::Response(string body, int status, string contentType) : HTTPObject(std::move(body)),
  80. status(status),
  81. contentType(std::move(contentType)) {
  82. }
  83. http::HTTPObject::HTTPObject(string body) : body(std::move(body)) {
  84. }