123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- #ifndef KBF_HTTP_CLIENT_H
- #define KBF_HTTP_CLIENT_H
- #include <string>
- #include <memory>
- #include <esp_err.h>
- #include <esp_http_client.h>
- #include <nlohmann_json/json.hpp>
- #include "kbf/http/common.h"
- namespace kbf::http {
- /**
- * @brief HTTP Client.
- *
- * @note May only perform 1 request at a time, but can be (and should be) reused afterwards.
- */
- class Client {
- public:
- /** @brief Tag used for logging. */
- static constexpr const char *TAG = "kbf::http::Client";
- /**
- * @brief Constructor.
- *
- * @warning Async mode is only supported by IDF for HTTPS.
- *
- * @param timeoutMs request timeout in milliseconds; 0 means no timeout; default is 0
- * @param async perform request asynchronously; default is false
- */
- explicit Client(int timeoutMs = 0, bool async = false);
- /**
- * @brief Destructor.
- *
- * Calls esp_http_client_cleanup().
- */
- ~Client();
- /**
- * @brief Performs an HTTP GET.
- *
- * Calls onSuccess() when a response is received (even if it's a HTTP 4XX), or onError() on failure
- * (e.g. socket error)
- *
- * @param url url to fetch
- * @param headers optional map<string, string> of headers
- * @return HTTP response
- */
- std::shared_ptr<Response>
- get(const std::string &url,
- const std::optional<const std::map<std::string, std::string>> &headers = std::nullopt);
- /**
- * @brief Performs an HTTP POST.
- *
- * @param url url to post to
- * @param data JSON data
- * @param headers optional map<string, string> of headers
- * @return HTTP response
- */
- std::shared_ptr<Response>
- post(const std::string &url, const nlohmann::json &data,
- const std::optional<const std::map<std::string, std::string>> &headers = std::nullopt);
- /**
- * @brief Called after the response is received.
- *
- * @note "Success" here means that the request went through and a response was received.
- * This method will be called even if the server returned an error status (HTTP 4XX)
- *
- * @param client reference to the Client that issued the request
- * @param response struct containing the HTTP response data
- */
- void (*onSuccess)(Client &client, const Response &response) = nullptr;
- /**
- * @brief Returns whether a request is currently in progress.
- *
- * @return true if a request is currently in progress; false otherwise
- */
- [[nodiscard]] bool isRunning() const { return running; }
- /**
- * @brief Closes the connection if it was persistent (i.e. keep-alive or HTTP/1.1).
- */
- void disconnect();
- /**
- * @brief Adds a certificate to the global CA store.
- *
- * @param start
- * @param end
- */
- static void addCert(const unsigned char *start, const unsigned char *const end);
- /**
- * @brief Frees the global CA store.
- *
- * @warning Calling this will result in heap corruption when disconnecting if there are any open connections.
- * Make sure to disconnect() all clients before calling this.
- */
- static void clearCerts();
- /** @brief Request timeout in milliseconds. */
- const int timeoutMs;
- /** @brief Async mode */
- const bool async;
- private:
- void init();
- std::shared_ptr<kbf::http::Response>
- performRequest(kbf::http::Method method, const std::string &url, const nlohmann::json *postData,
- const std::optional<const std::map<std::string, std::string>> &headers = std::nullopt);
- static void updateResponse(Client &client);
- /**
- * @brief Processes events from esp_http_client.
- *
- * @return
- */
- static esp_err_t handleHttpEvent(esp_http_client_event_t *);
- esp_http_client_handle_t handle{};
- std::string buffer;
- std::shared_ptr<Response> response;
- bool running = false;
- bool retry = false;
- };
- }
- #endif //KBF_HTTP_CLIENT_H
|