123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- #include "kbf/http/common.h"
- #include <regex>
- #include <utility>
- #include <esp_log.h>
- #include <esp_http_server.h>
- #include "kbf/macros.h"
- using namespace kbf;
- void http::HTTPObject::parseToMap(map<string, string> &target, const string &buffer) {
- auto queryString = string(buffer);
- std::regex regex("([\\w]+)=([\\w]+)");
- std::smatch submatch;
- while (std::regex_search(queryString, submatch, regex)) {
- ESP_LOGD(TAG, " parsed: %s = %s", submatch[1].str().c_str(), submatch[2].str().c_str());
- target[submatch[1]] = submatch[2];
- queryString = submatch.suffix();
- }
- }
- http::Request::Request(httpd_req_t *httpdRequest) {
- this->httpdRequest = httpdRequest;
- method = static_cast<Method>(httpdRequest->method);
- uri = httpdRequest->uri;
- for (const auto &name : acceptedHeaders) {
- readHeader(name);
- }
- readQuery();
- readBody();
- }
- string http::Request::readHeader(const string &header) {
- auto len = httpd_req_get_hdr_value_len(httpdRequest, header.c_str());
- if (len == 0) {
- ESP_LOGD(TAG, " header not found: %s", header.c_str());
- return "";
- }
- char buffer[len + 1];
- CHECK(httpd_req_get_hdr_value_str(httpdRequest, header.c_str(), buffer, len + 1));
- ESP_LOGD(TAG, " found header: %s: %s", header.c_str(), buffer);
- headers[header] = buffer;
- return buffer;
- }
- void http::Request::readQuery() {
- auto queryLen = httpd_req_get_url_query_len(httpdRequest);
- char buffer[queryLen + 1];
- auto err = httpd_req_get_url_query_str(httpdRequest, buffer, queryLen + 1);
- if (err == ESP_ERR_NOT_FOUND) {
- ESP_LOGD(TAG, "no query found");
- return;
- } else
- CHECK(err);
- ESP_LOGD(TAG, "found query: %s", buffer);
- parseToMap(query, buffer);
- }
- void http::Request::readBody() {
- if (httpdRequest->content_len == 0) {
- return;
- }
- ESP_LOGD(TAG, "reading body, length = %d", httpdRequest->content_len);
- // TODO check if we have enough memory for the content!
- char buffer[httpdRequest->content_len];
- for (int i = 1; i <= MAX_READ_RETRY; i++) {
- int ret;
- if ((ret = httpd_req_recv(httpdRequest, buffer, httpdRequest->content_len)) <= 0) {
- if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
- if (i == MAX_READ_RETRY) {
- ESP_LOGE(TAG, "socket timeout, giving up");
- break;
- }
- ESP_LOGW(TAG, "socket timeout, retrying (attempt %d)", i);
- continue;
- }
- ESP_LOGE(TAG, "socket read failed: %d (%s)", ret, esp_err_to_name(ret));
- } else {
- body = string(buffer, httpdRequest->content_len);
- ESP_LOGD(TAG, " read: \"%s\"", body.c_str());
- parseToMap(postData, body);
- break;
- }
- }
- }
- http::Response::Response(string body, int status, string contentType) : HTTPObject(std::move(body)),
- status(status),
- contentType(std::move(contentType)) {
- }
- http::HTTPObject::HTTPObject(string body) : body(std::move(body)) {
- }
|