Bugfix/http client (#2867)

* Fix persistance issue found, see ESP8266 issue #6152

* Correcting the parsing of the header for HTTP1.0

* Send 'Connection: Close' header in case of HTTP1.0

* Let reuse connection depend on protocol used: HTTP1.0 or HTTP1.1

* Fixed reuse, added null ptr checks, added check for _trainsportTraits in connect() in case _client was set null

* Fix reuse connection issues, similar to ESP8266 PR #6176
This commit is contained in:
Jeroen88 2019-08-20 16:18:09 +02:00 committed by Me No Dev
parent 5137fc5c80
commit f4acac4c2b
2 changed files with 42 additions and 14 deletions

View File

@ -1,3 +1,4 @@
#include <HardwareSerial.h>
/** /**
* HTTPClient.cpp * HTTPClient.cpp
* *
@ -195,6 +196,11 @@ bool HTTPClient::begin(String url, const char* CAcert)
} }
_secure = true; _secure = true;
_transportTraits = TransportTraitsPtr(new TLSTraits(CAcert)); _transportTraits = TransportTraitsPtr(new TLSTraits(CAcert));
if(!_transportTraits) {
log_e("could not create transport traits");
return false;
}
return true; return true;
} }
@ -215,6 +221,11 @@ bool HTTPClient::begin(String url)
return begin(url, (const char*)NULL); return begin(url, (const char*)NULL);
} }
_transportTraits = TransportTraitsPtr(new TransportTraits()); _transportTraits = TransportTraitsPtr(new TransportTraits());
if(!_transportTraits) {
log_e("could not create transport traits");
return false;
}
return true; return true;
} }
#endif // HTTPCLIENT_1_1_COMPATIBLE #endif // HTTPCLIENT_1_1_COMPATIBLE
@ -333,7 +344,8 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, const char* CAcer
*/ */
void HTTPClient::end(void) void HTTPClient::end(void)
{ {
disconnect(); disconnect(false);
clear();
} }
@ -342,7 +354,7 @@ void HTTPClient::end(void)
* disconnect * disconnect
* close the TCP socket * close the TCP socket
*/ */
void HTTPClient::disconnect() void HTTPClient::disconnect(bool preserveClient)
{ {
if(connected()) { if(connected()) {
if(_client->available() > 0) { if(_client->available() > 0) {
@ -357,7 +369,9 @@ void HTTPClient::disconnect()
} else { } else {
log_d("tcp stop\n"); log_d("tcp stop\n");
_client->stop(); _client->stop();
if(!preserveClient) {
_client = nullptr; _client = nullptr;
}
#ifdef HTTPCLIENT_1_1_COMPATIBLE #ifdef HTTPCLIENT_1_1_COMPATIBLE
if(_tcpDeprecated) { if(_tcpDeprecated) {
_transportTraits.reset(nullptr); _transportTraits.reset(nullptr);
@ -456,6 +470,7 @@ void HTTPClient::setTimeout(uint16_t timeout)
void HTTPClient::useHTTP10(bool useHTTP10) void HTTPClient::useHTTP10(bool useHTTP10)
{ {
_useHTTP10 = useHTTP10; _useHTTP10 = useHTTP10;
_reuse = !useHTTP10;
} }
/** /**
@ -816,7 +831,8 @@ int HTTPClient::writeToStream(Stream * stream)
return returnError(HTTPC_ERROR_ENCODING); return returnError(HTTPC_ERROR_ENCODING);
} }
end(); // end();
disconnect(true);
return ret; return ret;
} }
@ -970,9 +986,12 @@ bool HTTPClient::hasHeader(const char* name)
*/ */
bool HTTPClient::connect(void) bool HTTPClient::connect(void)
{ {
if(connected()) { if(connected()) {
if(_reuse) {
log_d("already connected, reusing connection");
} else {
log_d("already connected, try reuse!"); log_d("already connected, try reuse!");
}
while(_client->available() > 0) { while(_client->available() > 0) {
_client->read(); _client->read();
} }
@ -980,8 +999,12 @@ bool HTTPClient::connect(void)
} }
#ifdef HTTPCLIENT_1_1_COMPATIBLE #ifdef HTTPCLIENT_1_1_COMPATIBLE
if(!_client) { if(_transportTraits && !_client) {
_tcpDeprecated = _transportTraits->create(); _tcpDeprecated = _transportTraits->create();
if(!_tcpDeprecated) {
log_e("failed to create client");
return false;
}
_client = _tcpDeprecated.get(); _client = _tcpDeprecated.get();
} }
#endif #endif
@ -1080,11 +1103,12 @@ int HTTPClient::handleHeaderResponse()
return HTTPC_ERROR_NOT_CONNECTED; return HTTPC_ERROR_NOT_CONNECTED;
} }
_canReuse = !_useHTTP10; clear();
_canReuse = _reuse;
String transferEncoding; String transferEncoding;
_returnCode = -1;
_size = -1;
_transferEncoding = HTTPC_TE_IDENTITY; _transferEncoding = HTTPC_TE_IDENTITY;
unsigned long lastDataTime = millis(); unsigned long lastDataTime = millis();
@ -1099,8 +1123,10 @@ int HTTPClient::handleHeaderResponse()
log_v("RX: '%s'", headerLine.c_str()); log_v("RX: '%s'", headerLine.c_str());
if(headerLine.startsWith("HTTP/1.")) { if(headerLine.startsWith("HTTP/1.")) {
if(_canReuse) {
_canReuse = (headerLine[sizeof "HTTP/1." - 1] != '0');
}
_returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt(); _returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
_canReuse = (_returnCode != '0');
} else if(headerLine.indexOf(':')) { } else if(headerLine.indexOf(':')) {
String headerName = headerLine.substring(0, headerLine.indexOf(':')); String headerName = headerLine.substring(0, headerLine.indexOf(':'));
String headerValue = headerLine.substring(headerLine.indexOf(':') + 1); String headerValue = headerLine.substring(headerLine.indexOf(':') + 1);
@ -1110,8 +1136,10 @@ int HTTPClient::handleHeaderResponse()
_size = headerValue.toInt(); _size = headerValue.toInt();
} }
if(headerName.equalsIgnoreCase("Connection")) { if(_canReuse && headerName.equalsIgnoreCase("Connection")) {
_canReuse = headerValue.equalsIgnoreCase("keep-alive"); if(headerValue.indexOf("close") >= 0 && headerValue.indexOf("keep-alive") < 0) {
_canReuse = false;
}
} }
if(headerName.equalsIgnoreCase("Transfer-Encoding")) { if(headerName.equalsIgnoreCase("Transfer-Encoding")) {

View File

@ -197,7 +197,7 @@ protected:
}; };
bool beginInternal(String url, const char* expectedProtocol); bool beginInternal(String url, const char* expectedProtocol);
void disconnect(); void disconnect(bool preserveClient = false);
void clear(); void clear();
int returnError(int error); int returnError(int error);
bool connect(void); bool connect(void);