-
Notifications
You must be signed in to change notification settings - Fork 18
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?
Conversation
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request replaces the Arduino HTTP Client library with the ESP-IDF native HTTP client implementation. The change represents a significant architectural shift towards using ESP32's built-in networking capabilities, improving platform integration and potentially reducing dependency on third-party libraries.
Key Changes:
- Introduced new HTTP client architecture with
HTTPClient,HTTPClientState,HTTPResponse, andJsonResponseclasses - Replaced string_view URL parameters with const char* for HTTP client APIs
- Refactored rate limiting into a separate
RateLimitersmodule - Removed the old
HTTPRequestManagerimplementation and replaced all usages throughout the codebase
Reviewed changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| src/util/DomainUtils.cpp | New utility to extract domain from URL (critical bug: missing assignment on line 11) |
| src/util/ParitionUtils.cpp | Updated to use new HTTP client; logic error in status code check (line 63) |
| src/serialization/JsonAPI.cpp | Removed unused code parameter from JSON parsing functions |
| src/serial/command_handlers/domain.cpp | Updated to use new HTTP client with error handling |
| src/serial/command_handlers/authtoken.cpp | Updated to use new HTTP client in scoped block |
| src/serial/SerialInputHandler.cpp | Removed unused import |
| src/http/RateLimiters.cpp | New rate limiter management module extracted from old implementation |
| src/http/JsonAPI.cpp | Refactored to use new HTTP client, simplified header setting |
| src/http/HTTPRequestManager.cpp | Deleted - replaced by new implementation |
| src/http/HTTPClientState.cpp | New ESP-IDF HTTP client state management (bug in constructor initialization line 21, log message bug line 181) |
| src/http/HTTPClient.cpp | New HTTP client facade providing Get and GetJson methods |
| src/OtaUpdateManager.cpp | Updated all HTTP requests to use new client |
| src/GatewayConnectionManager.cpp | Updated API calls to use new HTTP client with improved error handling |
| include/util/PartitionUtils.h | Changed parameter type from string_view to const char* |
| include/util/DomainUtils.h | New header for domain extraction utility |
| include/serialization/JsonAPI.h | Updated parsing function signatures to remove code parameter, forward declared cJSON |
| include/http/*.h | New HTTP client interface headers (HTTPError.h has critical bug: empty error strings) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
Cannot merge until we switch over to ESP-IDF due to inability configure global certs when arduino es-idf framework has precompiled binaries |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 27 out of 27 changed files in this pull request and generated 11 comments.
Comments suppressed due to low confidence (1)
platformio.ini:48
- These configuration flags completely disable SSL/TLS certificate verification, making all HTTPS connections vulnerable to man-in-the-middle attacks. This is a serious security vulnerability that should not be enabled in production code.
Consider using proper certificate validation with either a CA bundle or certificate pinning instead of disabling verification entirely.
-DCONFIG_ESP_TLS_INSECURE=y
-DCONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| HTTPClient(const char* url, uint32_t timeoutMs = 10'000) | ||
| : m_state(std::make_shared<HTTPClientState>(url, timeoutMs)) | ||
| { | ||
| } |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new HTTPClient implementation does not integrate with the rate limiting system. The old implementation called _getRateLimiter() and checked rateLimiter->tryRequest() before making requests. Without this integration, the application may exceed API rate limits and get blocked by the server. Consider integrating the RateLimiters::GetRateLimiter functionality into the HTTPClient.
|
|
||
| auto content = response.ReadString(); | ||
| if (content.error != HTTP::HTTPError::None) { | ||
| OS_LOGE(TAG, "Failed to fetch hashes: %s [%u] %s", HTTP::HTTPErrorToString(response.Error()), response.StatusCode(), content.data.c_str()); |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue - attempting to log content.data.c_str() when an error has occurred. The content data may not be valid when content.error is not None.
| OS_LOGE(TAG, "Failed to fetch hashes: %s [%u] %s", HTTP::HTTPErrorToString(response.Error()), response.StatusCode(), content.data.c_str()); | |
| OS_LOGE(TAG, "Failed to fetch hashes: %s [%u]", HTTP::HTTPErrorToString(response.Error()), response.StatusCode()); |
| OS_LOGE(TAG, "Unexpected response code: %d", response.code); | ||
| auto content = response.ReadJson(); | ||
| if (content.error != HTTP::HTTPError::None) { | ||
| OS_LOGE(TAG, "Error while reading response: %s %d", HTTP::HTTPErrorToString(response.Error()), response.StatusCode()); |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue - using response.Error() when the error occurred during content reading. Should use content.error instead.
| OS_LOGE(TAG, "Error while reading response: %s %d", HTTP::HTTPErrorToString(response.Error()), response.StatusCode()); | |
| OS_LOGE(TAG, "Error while reading response: %s %d", HTTP::HTTPErrorToString(content.error), response.StatusCode()); |
| OS_LOGE(TAG, "Unexpected response code: %d", response.code); | ||
| auto content = response.ReadJson(); | ||
| if (content.error != HTTP::HTTPError::None) { | ||
| OS_LOGE(TAG, "Error while reading response: %s %d", HTTP::HTTPErrorToString(response.Error()), response.StatusCode()); |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue - using response.Error() when the error occurred during content reading. Should use content.error instead.
| OS_LOGE(TAG, "Error while reading response: %s %d", HTTP::HTTPErrorToString(response.Error()), response.StatusCode()); | |
| OS_LOGE(TAG, "Error while reading response: %s %d", HTTP::HTTPErrorToString(content.error), response.StatusCode()); |
|
|
||
| if (key == "retry-after") { | ||
| uint32_t seconds = 0; | ||
| if (!Convert::ToUint32(value, seconds) || seconds <= 0) { |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition seconds <= 0 will always be false because seconds is an unsigned integer (uint32_t). If conversion fails and returns 0, this check won't catch it. Consider checking if the conversion succeeded first, or use a different approach to validate the retry-after value.
| if (!Convert::ToUint32(value, seconds) || seconds <= 0) { | |
| if (!Convert::ToUint32(value, seconds) || seconds == 0) { |
| OS_LOGI(TAG, "Successfully connected to \"%.*s\", version: %s, commit: %s, current time: %s", arg.length(), arg.data(), resp.data.version.c_str(), resp.data.commit.c_str(), resp.data.currentTime.c_str()); | ||
| auto content = response.ReadJson(); | ||
| if (content.error != OpenShock::HTTP::HTTPError::None) { | ||
| SERPR_ERROR("Tried to read response from backend, but failed (%s), refusing to save domain to config", OpenShock::HTTP::HTTPErrorToString(response.Error())); |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message calls response.Error() but should call content.error since the error occurred during the ReadJson operation, not during the initial request. The response's Error() method may not reflect the actual error that occurred during content reading.
| SERPR_ERROR("Tried to read response from backend, but failed (%s), refusing to save domain to config", OpenShock::HTTP::HTTPErrorToString(response.Error())); | |
| SERPR_ERROR("Tried to read response from backend, but failed (%s), refusing to save domain to config", OpenShock::HTTP::HTTPErrorToString(content.error)); |
|
|
||
| auto content = response.ReadString(); | ||
| if (content.error != HTTP::HTTPError::None) { | ||
| OS_LOGE(TAG, "Failed to fetch list: %s [%u] %s", HTTP::HTTPErrorToString(response.Error()), response.StatusCode(), content.data.c_str()); |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error logging is inconsistent - it uses response.Error() and response.StatusCode() but also tries to log content.data.c_str(). However, if content.error is not None, then content.data may be empty or invalid. Consider logging only the error information without attempting to log the potentially invalid content data.
| OS_LOGE(TAG, "Failed to fetch list: %s [%u] %s", HTTP::HTTPErrorToString(response.Error()), response.StatusCode(), content.data.c_str()); | |
| OS_LOGE(TAG, "Failed to fetch list: %s [%u]", HTTP::HTTPErrorToString(response.Error()), response.StatusCode()); |
|
|
||
| auto content = response.ReadString(); | ||
| if (content.error != HTTP::HTTPError::None) { | ||
| OS_LOGE(TAG, "Failed to fetch firmware version: %s [%u] %s", HTTP::HTTPErrorToString(response.Error()), response.StatusCode(), content.data.c_str()); |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue as line 444 - attempting to log content.data.c_str() when content.error indicates an error occurred. The content data may be empty or invalid in this case.
| OS_LOGE(TAG, "Failed to fetch firmware version: %s [%u] %s", HTTP::HTTPErrorToString(response.Error()), response.StatusCode(), content.data.c_str()); | |
| OS_LOGE(TAG, "Failed to fetch firmware version: %s [%u]", HTTP::HTTPErrorToString(response.Error()), response.StatusCode()); |
| OS_LOGE(TAG, "Unexpected response code: %d", response.code); | ||
| auto content = response.ReadJson(); | ||
| if (content.error != HTTP::HTTPError::None) { | ||
| OS_LOGE(TAG, "Error while reading response: %s %d", HTTP::HTTPErrorToString(response.Error()), response.StatusCode()); |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message calls response.Error() when the error actually occurred during ReadJson(), so it should reference content.error instead. The response's Error() method will likely return HTTPError::None since the initial request succeeded.
| OS_LOGE(TAG, "Error while reading response: %s %d", HTTP::HTTPErrorToString(response.Error()), response.StatusCode()); | |
| OS_LOGE(TAG, "Error while reading response: %s %d", HTTP::HTTPErrorToString(content.error), response.StatusCode()); |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Cpp-Linter Report
|
No description provided.