-
Notifications
You must be signed in to change notification settings - Fork 21
refactor: Replace Arduino HTTP Client with esp native #391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 24 commits
657ab37
ff81cf6
22dc664
8ceac76
042f28d
50e317f
9dcc162
49be717
eb734c7
c342d31
664a589
9604c39
d7774cc
0d966e3
979a17d
8cc417b
c0ee503
e8d2790
d83d888
3a274f5
bb36316
c44bbc0
0bfc377
454a508
a6bc157
7e79d41
614e4c8
68cf530
b59e4b9
435e6ef
3579cee
c9f2094
da86842
3de2c16
f752a17
441688f
6b85a36
03ad6f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| #pragma once | ||
|
|
||
| #include <cstdint> | ||
| #include <functional> | ||
|
|
||
| namespace OpenShock::HTTP { | ||
| using DownloadCallback = std::function<bool(std::size_t offset, const uint8_t* data, std::size_t len)>; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| #pragma once | ||
|
|
||
| #include <cstdint> | ||
| #include <functional> | ||
|
|
||
| namespace OpenShock::HTTP { | ||
| using GotContentLengthCallback = std::function<bool(int contentLength)>; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| #pragma once | ||
|
|
||
| #include "Common.h" | ||
| #include "http/HTTPClientState.h" | ||
| #include "http/HTTPResponse.h" | ||
| #include "http/JsonResponse.h" | ||
|
|
||
| #include<esp_err.h> | ||
|
|
||
| #include <cstdint> | ||
| #include <memory> | ||
|
|
||
| namespace OpenShock::HTTP { | ||
| class HTTPClient { | ||
| DISABLE_COPY(HTTPClient); | ||
| DISABLE_MOVE(HTTPClient); | ||
|
|
||
| public: | ||
| HTTPClient(uint32_t timeoutMs = 10'000) | ||
| : m_state(std::make_shared<HTTPClientState>(timeoutMs)) | ||
| { | ||
| } | ||
|
Comment on lines
+20
to
+23
|
||
|
|
||
| inline esp_err_t SetHeader(const char* key, const char* value) { | ||
| return m_state->SetHeader(key, value); | ||
| } | ||
|
|
||
| inline HTTPResponse Get(const char* url) { | ||
| auto response = GetInternal(url); | ||
| if (response.error != HTTPError::None) return response.error; | ||
|
|
||
| return HTTP::HTTPResponse(m_state, response.data.statusCode, response.data.contentLength); | ||
| } | ||
| template<typename T> | ||
| inline JsonResponse<T> GetJson(const char* url, JsonParserFn<T> jsonParser) { | ||
| auto response = GetInternal(url); | ||
| if (response.error != HTTPError::None) return response.error; | ||
|
|
||
| return HTTP::JsonResponse(m_state, jsonParser, response.data.statusCode, response.data.contentLength); | ||
| } | ||
|
|
||
| inline esp_err_t Close() { | ||
| return m_state->Close(); | ||
| } | ||
| private: | ||
| struct InternalResult { | ||
| HTTPError error; | ||
| HTTPClientState::StartRequestResult data; | ||
| }; | ||
| InternalResult GetInternal(const char* url); | ||
|
|
||
| std::shared_ptr<HTTPClientState> m_state; | ||
| }; | ||
| } // namespace OpenShock::HTTP | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| #pragma once | ||
|
|
||
| #include "Common.h" | ||
| #include "http/DownloadCallback.h" | ||
| #include "http/HTTPError.h" | ||
| #include "http/JsonParserFn.h" | ||
| #include "http/ReadResult.h" | ||
|
|
||
| #include <cJSON.h> | ||
|
|
||
| #include <esp_http_client.h> | ||
|
|
||
| #include <string> | ||
| #include <string_view> | ||
| #include <variant> | ||
| #include <vector> | ||
|
|
||
| namespace OpenShock::HTTP { | ||
| class HTTPClientState { | ||
| DISABLE_COPY(HTTPClientState); | ||
| DISABLE_MOVE(HTTPClientState); | ||
| public: | ||
| HTTPClientState(uint32_t timeoutMs); | ||
| ~HTTPClientState(); | ||
|
|
||
| inline esp_err_t SetHeader(const char* key, const char* value) { | ||
| return esp_http_client_set_header(m_handle, key, value); | ||
| } | ||
|
|
||
| struct [[nodiscard]] StartRequestResult { | ||
| uint16_t statusCode; | ||
| bool isChunked; | ||
| uint32_t contentLength; | ||
| }; | ||
|
|
||
| std::variant<StartRequestResult, HTTPError> StartRequest(esp_http_client_method_t method, const char* url, int writeLen); | ||
|
|
||
| // High-throughput streaming logic | ||
| ReadResult<uint32_t> ReadStreamImpl(DownloadCallback cb); | ||
|
|
||
| ReadResult<std::string> ReadStringImpl(uint32_t reserve); | ||
|
|
||
| template<typename T> | ||
| inline ReadResult<T> ReadJsonImpl(uint32_t reserve, JsonParserFn<T> jsonParser) | ||
| { | ||
| auto response = ReadStringImpl(reserve); | ||
| if (response.error != HTTPError::None) { | ||
| return response.error; | ||
| } | ||
|
|
||
| cJSON* json = cJSON_ParseWithLength(response.data.c_str(), response.data.length()); | ||
| if (json == nullptr) { | ||
| return HTTPError::ParseFailed; | ||
| } | ||
|
|
||
| T data; | ||
| if (!jsonParser(json, data)) { | ||
| return HTTPError::ParseFailed; | ||
| } | ||
|
|
||
| cJSON_Delete(json); | ||
|
|
||
| return data; | ||
| } | ||
|
|
||
| inline esp_err_t Close() { | ||
| return esp_http_client_close(m_handle); | ||
| } | ||
| private: | ||
| static esp_err_t EventHandler(esp_http_client_event_t* evt); | ||
| esp_err_t EventHeaderHandler(std::string key, std::string value); | ||
|
|
||
| esp_http_client_handle_t m_handle; | ||
| bool m_reading; | ||
| std::vector<std::pair<std::string, std::string>> m_headers; | ||
| }; | ||
| } // namespace OpenShock::HTTP |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| #pragma once | ||
|
|
||
| namespace OpenShock::HTTP { | ||
| enum class HTTPError { | ||
| None, | ||
| InternalError, | ||
| RateLimited, | ||
| InvalidUrl, | ||
| InvalidHttpMethod, | ||
| NetworkError, | ||
| ConnectionClosed, | ||
| SizeLimitExceeded, | ||
| Aborted, | ||
| ParseFailed | ||
| }; | ||
|
|
||
| inline const char* HTTPErrorToString(HTTPError error) { | ||
| switch (error) | ||
| { | ||
| case HTTPError::None: | ||
| return ""; | ||
| case HTTPError::InternalError: | ||
| return ""; | ||
| case HTTPError::RateLimited: | ||
| return ""; | ||
| case HTTPError::InvalidUrl: | ||
| return ""; | ||
| case HTTPError::InvalidHttpMethod: | ||
| return ""; | ||
| case HTTPError::NetworkError: | ||
| return ""; | ||
| case HTTPError::ConnectionClosed: | ||
| return ""; | ||
| case HTTPError::SizeLimitExceeded: | ||
| return ""; | ||
| case HTTPError::Aborted: | ||
| return ""; | ||
| case HTTPError::ParseFailed: | ||
| return ""; | ||
| default: | ||
| return ""; | ||
|
hhvrc marked this conversation as resolved.
Outdated
|
||
| } | ||
| } | ||
| } // namespace OpenShock::HTTP | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| #pragma once | ||
|
|
||
| #include "Common.h" | ||
| #include "http/DownloadCallback.h" | ||
| #include "http/HTTPClientState.h" | ||
| #include "http/JsonParserFn.h" | ||
| #include "http/ReadResult.h" | ||
|
|
||
| #include <cstdint> | ||
| #include <memory> | ||
| #include <string> | ||
|
|
||
| namespace OpenShock::HTTP { | ||
| class HTTPClient; | ||
| class [[nodiscard]] HTTPResponse { | ||
| DISABLE_DEFAULT(HTTPResponse); | ||
| DISABLE_COPY(HTTPResponse); | ||
| DISABLE_MOVE(HTTPResponse); | ||
|
|
||
| friend class HTTPClient; | ||
|
|
||
| HTTPResponse(std::shared_ptr<HTTPClientState> state, uint16_t statusCode, uint32_t contentLength) | ||
| : m_state(state) | ||
| , m_error(HTTPError::None) | ||
| , m_statusCode(statusCode) | ||
| , m_contentLength(contentLength) | ||
| { | ||
| } | ||
| public: | ||
| HTTPResponse(HTTPError error) | ||
| : m_state() | ||
| , m_error(error) | ||
| , m_statusCode(0) | ||
| , m_contentLength(0) | ||
| { | ||
| } | ||
|
|
||
| inline bool Ok() const { return m_error == HTTPError::None && !m_state.expired(); } | ||
| inline HTTPError Error() const { return m_error; } | ||
| inline uint16_t StatusCode() const { return m_statusCode; } | ||
| inline uint32_t ContentLength() const { return m_contentLength; } | ||
|
|
||
| inline ReadResult<uint32_t> ReadStream(DownloadCallback downloadCallback) { | ||
| auto locked = m_state.lock(); | ||
| if (locked == nullptr) return HTTPError::ConnectionClosed; | ||
|
|
||
| return locked->ReadStreamImpl(downloadCallback); | ||
| } | ||
|
|
||
| inline ReadResult<std::string> ReadString() { | ||
| auto locked = m_state.lock(); | ||
| if (locked == nullptr) return HTTPError::ConnectionClosed; | ||
|
|
||
| return locked->ReadStringImpl(m_contentLength); | ||
| } | ||
|
|
||
| template<typename T> | ||
| inline ReadResult<T> ReadJson(JsonParserFn<T> jsonParser) | ||
| { | ||
| auto locked = m_state.lock(); | ||
| if (locked == nullptr) return HTTPError::ConnectionClosed; | ||
|
|
||
| return locked->ReadJsonImpl(m_contentLength, jsonParser); | ||
| } | ||
| private: | ||
| std::weak_ptr<HTTPClientState> m_state; | ||
| HTTPError m_error; | ||
| uint16_t m_statusCode; | ||
| uint32_t m_contentLength; | ||
| }; | ||
| } // namespace OpenShock::HTTP |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #pragma once | ||
|
|
||
| #include <cstdint> | ||
| #include <functional> | ||
|
|
||
| class cJSON; | ||
|
|
||
| namespace OpenShock::HTTP { | ||
| template<typename T> | ||
| using JsonParserFn = std::function<bool(const cJSON* json, T& data)>; | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.