1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-21 10:26:06 +03:00

Reduce temporary string creation in HTTPClient::sendHeader (#6937)

* Reduce temporary string creation/reallocation in HTTPClient

This improves both performance due to fewer memory allocations/copies
as well as reduces code size by ~ 25% (150 bytes)

* Add more correct reservation calculation

Co-authored-by: Develo <deveyes@gmail.com>
This commit is contained in:
Dirk Mueller 2019-12-29 04:48:47 +01:00 committed by Earle F. Philhower, III
parent 3197d2ac4e
commit 5d5200af41

View File

@ -1076,12 +1076,14 @@ String HTTPClient::errorToString(int error)
void HTTPClient::addHeader(const String& name, const String& value, bool first, bool replace) void HTTPClient::addHeader(const String& name, const String& value, bool first, bool replace)
{ {
// not allow set of Header handled by code // not allow set of Header handled by code
if(!name.equalsIgnoreCase(F("Connection")) && if (!name.equalsIgnoreCase(F("Connection")) &&
!name.equalsIgnoreCase(F("User-Agent")) && !name.equalsIgnoreCase(F("User-Agent")) &&
!name.equalsIgnoreCase(F("Host")) && !name.equalsIgnoreCase(F("Host")) &&
!(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())){ !(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())) {
String headerLine = name; String headerLine;
headerLine.reserve(name.length() + value.length() + 4);
headerLine += name;
headerLine += ": "; headerLine += ": ";
if (replace) { if (replace) {
@ -1094,13 +1096,12 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first,
headerLine += value; headerLine += value;
headerLine += "\r\n"; headerLine += "\r\n";
if(first) { if (first) {
_headers = headerLine + _headers; _headers = headerLine + _headers;
} else { } else {
_headers += headerLine; _headers += headerLine;
} }
} }
} }
void HTTPClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) void HTTPClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount)
@ -1225,7 +1226,18 @@ bool HTTPClient::sendHeader(const char * type)
return false; return false;
} }
String header = String(type) + ' ' + (_uri.length() ? _uri : F("/")) + F(" HTTP/1."); String header;
// 128: Arbitrarily chosen to have enough buffer space for avoiding internal reallocations
header.reserve(_headers.length() + _uri.length() +
_base64Authorization.length() + _host.length() + _userAgent.length() + 128);
header += type;
header += ' ';
if (_uri.length()) {
header += _uri;
} else {
header += '/';
}
header += F(" HTTP/1.");
if(_useHTTP10) { if(_useHTTP10) {
header += '0'; header += '0';
@ -1233,33 +1245,31 @@ bool HTTPClient::sendHeader(const char * type)
header += '1'; header += '1';
} }
header += String(F("\r\nHost: ")) + _host; header += F("\r\nHost: ");
header += _host;
if (_port != 80 && _port != 443) if (_port != 80 && _port != 443)
{ {
header += ':'; header += ':';
header += String(_port); header += String(_port);
} }
header += String(F("\r\nUser-Agent: ")) + _userAgent + header += F("\r\nUser-Agent: ");
F("\r\nConnection: "); header += _userAgent;
if(_reuse) { if (!_useHTTP10) {
header += F("keep-alive"); header += F("\r\nAccept-Encoding: identity;q=1,chunked;q=0.1,*;q=0");
} else {
header += F("close");
} }
if (_base64Authorization.length()) {
header += F("\r\nAuthorization: Basic ");
header += _base64Authorization;
}
header += F("\r\nConnection: ");
header += _reuse ? F("keep-alive") : F("close");
header += "\r\n"; header += "\r\n";
if(!_useHTTP10) { header += _headers;
header += F("Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0\r\n"); header += "\r\n";
}
if(_base64Authorization.length()) {
header += F("Authorization: Basic ");
header += _base64Authorization;
header += "\r\n";
}
header += _headers + "\r\n";
DEBUG_HTTPCLIENT("[HTTP-Client] sending request header\n-----\n%s-----\n", header.c_str()); DEBUG_HTTPCLIENT("[HTTP-Client] sending request header\n-----\n%s-----\n", header.c_str());
@ -1290,20 +1300,23 @@ int HTTPClient::handleHeaderResponse()
size_t len = _client->available(); size_t len = _client->available();
if(len > 0) { if(len > 0) {
String headerLine = _client->readStringUntil('\n'); String headerLine = _client->readStringUntil('\n');
headerLine.trim(); // remove \r
lastDataTime = millis(); lastDataTime = millis();
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] RX: '%s'\n", headerLine.c_str()); DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] RX: '%s'\n", headerLine.c_str());
if(headerLine.startsWith("HTTP/1.")) { if (headerLine.startsWith(F("HTTP/1."))) {
if(_canReuse) { if (_canReuse) {
_canReuse = (headerLine[sizeof "HTTP/1." - 1] != '0'); _canReuse = (headerLine[sizeof "HTTP/1." - 1] != '0');
} }
_returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt(); _returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
} else if(headerLine.indexOf(':')) { continue;
String headerName = headerLine.substring(0, headerLine.indexOf(':')); }
String headerValue = headerLine.substring(headerLine.indexOf(':') + 1);
int headerSeparator = headerLine.indexOf(':');
if (headerSeparator > 0) {
String headerName = headerLine.substring(0, headerSeparator);
String headerValue = headerLine.substring(headerSeparator + 1);
headerValue.trim(); headerValue.trim();
if(headerName.equalsIgnoreCase(F("Content-Length"))) { if(headerName.equalsIgnoreCase(F("Content-Length"))) {
@ -1324,9 +1337,9 @@ int HTTPClient::handleHeaderResponse()
_location = headerValue; _location = headerValue;
} }
for(size_t i = 0; i < _headerKeysCount; i++) { for (size_t i = 0; i < _headerKeysCount; i++) {
if(_currentHeaders[i].key.equalsIgnoreCase(headerName)) { if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
if (_currentHeaders[i].value != "") { if (!_currentHeaders[i].value.isEmpty()) {
// Existing value, append this one with a comma // Existing value, append this one with a comma
_currentHeaders[i].value += ','; _currentHeaders[i].value += ',';
_currentHeaders[i].value += headerValue; _currentHeaders[i].value += headerValue;
@ -1336,9 +1349,12 @@ int HTTPClient::handleHeaderResponse()
break; // We found a match, stop looking break; // We found a match, stop looking
} }
} }
continue;
} }
if(headerLine == "") { headerLine.trim(); // remove \r
if (headerLine.isEmpty()) {
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: %d\n", _returnCode); DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: %d\n", _returnCode);
if(_size > 0) { if(_size > 0) {