Jelajahi Sumber

KBF-8 fix HTTP client retry method

Bence Balint 3 tahun lalu
induk
melakukan
3a86dda5b0
2 mengubah file dengan 44 tambahan dan 5 penghapusan
  1. 14 5
      src/http/client.cpp
  2. 30 0
      test/test_http.cpp

+ 14 - 5
src/http/client.cpp

@@ -2,6 +2,7 @@
 
 #include <freertos/task.h>
 #include <esp_log.h>
+#include <kbf/exception.h>
 
 #include "kbf/macros.h"
 
@@ -62,7 +63,8 @@ http::Client::performRequest(const kbf::http::Method method, const std::string &
         esp_http_client_set_header(handle, "Content-Type", "application/json");
         esp_http_client_set_post_field(handle, body.c_str(), body.length());
     } else {
-        ESP_LOGW(TAG, "unhandled method: %d", method);
+        ESP_LOGE(TAG, "unhandled method: %d", method);
+        throw KBFError("unknown HTTP method " + std::to_string(method));
     }
 
     if (headers) {
@@ -89,16 +91,23 @@ http::Client::performRequest(const kbf::http::Method method, const std::string &
     } else if (err == ESP_OK) {
         ESP_LOGD(TAG, "success");
         return response;
-    } else if (err == ESP_ERR_HTTP_FETCH_HEADER && !retry) {
+    } else if ((err == ESP_ERR_HTTP_FETCH_HEADER || err == ESP_FAIL) && !retry) {
         // TODO this will happen on timeout as well; perhaps set a retry limit in ctor / get / post?
-        ESP_LOGW(TAG, "fetching headers failed, maybe the connection was dropped? retrying...");
+        ESP_LOGW(TAG, "request failed, maybe the connection was dropped? retrying...");
         retry = true;
         esp_http_client_cleanup(handle);
         init();
-        return get(url);
+        if (method == http::GET) {
+            return get(url, headers);
+        } else if (method == http::POST) {
+            return post(url, *postData, headers);
+        } else {
+            throw KBFError("unknown HTTP method " + std::to_string(method));
+        }
     } else {
-        ESP_LOGE(TAG, "HTTP GET failed: %s", esp_err_to_name(err));
+        ESP_LOGE(TAG, "HTTP request failed: %s", esp_err_to_name(err));
         if (onError) onError(*this);
+        running = false;
         return nullptr;
     }
 }

+ 30 - 0
test/test_http.cpp

@@ -217,6 +217,36 @@ TEST_CASE("HTTP onResponseSent", "[kbf_http]") {
     wifi::stop();
 }
 
+TEST_CASE("HTTP Client errors", "[kbf_http]") {
+    wifi::start();
+
+    auto server = http::Server();
+    http::Response (*testGet)(const http::Request &, void *) = {[](const http::Request &request, void *) {
+        TEST_FAIL();
+        return http::Response();
+    }};
+    http::Response (*testPost)(const http::Request &, void *) = {[](const http::Request &request, void *) {
+        TEST_ASSERT_EQUAL_STRING("hax", request.readHeader("X-Hax").c_str());
+        return http::Response("OK");
+    }};
+    server.route({http::GET, "/test", testGet, nullptr});
+    server.route({http::POST, "/test", testPost, nullptr});
+    server.start();
+
+    auto client = http::Client();
+
+    auto response = client.get("http://localhost/non-existent");
+    TEST_ASSERT_EQUAL(404, response->status);
+
+    response = client.post("http://localhost/test", {{"foo", "bar"}}, {{{"X-Hax", "hax"}}});
+    TEST_ASSERT_EQUAL_STRING("OK", response->body.c_str());
+
+    response = client.get("http://non-existent-host-blabla.com/");
+    TEST_ASSERT_NULL(response);
+
+    wifi::stop();
+}
+
 TEST_CASE("HTTP CORS", "[notimplemented]") {
     TEST_FAIL_MESSAGE("not yet implemented");
 }