mirror of
https://github.com/esp8266/Arduino.git
synced 2025-09-11 05:52:31 +03:00
Movable HTTPClient and fixing WiFiClient copy (#8237)
- =default for default ctor, destructor, move ctor and the assignment move - use `std::unique_ptr<WiFiClient>` instead of raw pointer to the client - implement `virtual std::unique_ptr<WiFiClient> WiFiClient::clone()` to safely copy the WiFiClientSecure instance, without accidentally slicing it (i.e. using the pointer with incorrect type, calling base WiFiClient virtual methods) - replace headers pointer array with `std::unique_ptr<T[]>` to simplify the move operations - substitute userAgent with the default one when it is empty (may be a subject to change though, b/c now there is a global static `String`) Allow HTTPClient to be placed inside of movable classes (e.g. std::optional, requested in the linked issue) or to be returned from functions. Class logic stays as-is, only the underlying member types are changed. Notice that WiFiClient connection object is now copied, and the internal ClientContext will be preserved even after the original WiFiClient object was destroyed. replaces #8236 resolves #8231 and, possibly #5734
This commit is contained in:
@@ -28,6 +28,16 @@
|
||||
#include <StreamDev.h>
|
||||
#include <base64.h>
|
||||
|
||||
// per https://github.com/esp8266/Arduino/issues/8231
|
||||
// make sure HTTPClient can be utilized as a movable class member
|
||||
static_assert(std::is_default_constructible_v<HTTPClient>, "");
|
||||
static_assert(!std::is_copy_constructible_v<HTTPClient>, "");
|
||||
static_assert(std::is_move_constructible_v<HTTPClient>, "");
|
||||
static_assert(std::is_move_assignable_v<HTTPClient>, "");
|
||||
|
||||
static const char defaultUserAgentPstr[] PROGMEM = "ESP8266HTTPClient";
|
||||
const String HTTPClient::defaultUserAgent = defaultUserAgentPstr;
|
||||
|
||||
static int StreamReportToHttpClientReport (Stream::Report streamSendError)
|
||||
{
|
||||
switch (streamSendError)
|
||||
@@ -41,27 +51,6 @@ static int StreamReportToHttpClientReport (Stream::Report streamSendError)
|
||||
return 0; // never reached, keep gcc quiet
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*/
|
||||
HTTPClient::HTTPClient()
|
||||
: _client(nullptr), _userAgent(F("ESP8266HTTPClient"))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* destructor
|
||||
*/
|
||||
HTTPClient::~HTTPClient()
|
||||
{
|
||||
if(_client) {
|
||||
_client->stop();
|
||||
}
|
||||
if(_currentHeaders) {
|
||||
delete[] _currentHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPClient::clear()
|
||||
{
|
||||
_returnCode = 0;
|
||||
@@ -80,8 +69,6 @@ void HTTPClient::clear()
|
||||
* @return success bool
|
||||
*/
|
||||
bool HTTPClient::begin(WiFiClient &client, const String& url) {
|
||||
_client = &client;
|
||||
|
||||
// check for : (http: or https:)
|
||||
int index = url.indexOf(':');
|
||||
if(index < 0) {
|
||||
@@ -97,6 +84,8 @@ bool HTTPClient::begin(WiFiClient &client, const String& url) {
|
||||
}
|
||||
|
||||
_port = (protocol == "https" ? 443 : 80);
|
||||
_client = client.clone();
|
||||
|
||||
return beginInternal(url, protocol.c_str());
|
||||
}
|
||||
|
||||
@@ -112,7 +101,7 @@ bool HTTPClient::begin(WiFiClient &client, const String& url) {
|
||||
*/
|
||||
bool HTTPClient::begin(WiFiClient &client, const String& host, uint16_t port, const String& uri, bool https)
|
||||
{
|
||||
_client = &client;
|
||||
_client = client.clone();
|
||||
|
||||
clear();
|
||||
_host = host;
|
||||
@@ -462,7 +451,7 @@ int HTTPClient::sendRequest(const char * type, const uint8_t * payload, size_t s
|
||||
}
|
||||
|
||||
// transfer all of it, with send-timeout
|
||||
if (size && StreamConstPtr(payload, size).sendAll(_client) != size)
|
||||
if (size && StreamConstPtr(payload, size).sendAll(_client.get()) != size)
|
||||
return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED);
|
||||
|
||||
// handle Server Response (Header)
|
||||
@@ -563,7 +552,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size)
|
||||
}
|
||||
|
||||
// transfer all of it, with timeout
|
||||
size_t transferred = stream->sendSize(_client, size);
|
||||
size_t transferred = stream->sendSize(_client.get(), size);
|
||||
if (transferred != size)
|
||||
{
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] short write, asked for %d but got %d failed.\n", size, transferred);
|
||||
@@ -613,7 +602,7 @@ WiFiClient& HTTPClient::getStream(void)
|
||||
WiFiClient* HTTPClient::getStreamPtr(void)
|
||||
{
|
||||
if(connected()) {
|
||||
return _client;
|
||||
return _client.get();
|
||||
}
|
||||
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client] getStreamPtr: not connected\n");
|
||||
@@ -818,10 +807,7 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first,
|
||||
void HTTPClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount)
|
||||
{
|
||||
_headerKeysCount = headerKeysCount;
|
||||
if(_currentHeaders) {
|
||||
delete[] _currentHeaders;
|
||||
}
|
||||
_currentHeaders = new RequestArgument[_headerKeysCount];
|
||||
_currentHeaders = std::make_unique<RequestArgument[]>(_headerKeysCount);
|
||||
for(size_t i = 0; i < _headerKeysCount; i++) {
|
||||
_currentHeaders[i].key = headerKeys[i];
|
||||
}
|
||||
@@ -963,7 +949,7 @@ bool HTTPClient::sendHeader(const char * type)
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client] sending request header\n-----\n%s-----\n", header.c_str());
|
||||
|
||||
// transfer all of it, with timeout
|
||||
return StreamConstPtr(header).sendAll(_client) == header.length();
|
||||
return StreamConstPtr(header).sendAll(_client.get()) == header.length();
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user