1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +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)
{
// 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("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 += ": ";
if (replace) {
@ -1094,13 +1096,12 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first,
headerLine += value;
headerLine += "\r\n";
if(first) {
if (first) {
_headers = headerLine + _headers;
} else {
_headers += headerLine;
}
}
}
void HTTPClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount)
@ -1225,7 +1226,18 @@ bool HTTPClient::sendHeader(const char * type)
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) {
header += '0';
@ -1233,33 +1245,31 @@ bool HTTPClient::sendHeader(const char * type)
header += '1';
}
header += String(F("\r\nHost: ")) + _host;
header += F("\r\nHost: ");
header += _host;
if (_port != 80 && _port != 443)
{
header += ':';
header += String(_port);
}
header += String(F("\r\nUser-Agent: ")) + _userAgent +
F("\r\nConnection: ");
header += F("\r\nUser-Agent: ");
header += _userAgent;
if(_reuse) {
header += F("keep-alive");
} else {
header += F("close");
}
header += "\r\n";
if(!_useHTTP10) {
header += F("Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0\r\n");
if (!_useHTTP10) {
header += F("\r\nAccept-Encoding: identity;q=1,chunked;q=0.1,*;q=0");
}
if(_base64Authorization.length()) {
header += F("Authorization: Basic ");
if (_base64Authorization.length()) {
header += F("\r\nAuthorization: Basic ");
header += _base64Authorization;
header += "\r\n";
}
header += _headers + "\r\n";
header += F("\r\nConnection: ");
header += _reuse ? F("keep-alive") : F("close");
header += "\r\n";
header += _headers;
header += "\r\n";
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();
if(len > 0) {
String headerLine = _client->readStringUntil('\n');
headerLine.trim(); // remove \r
lastDataTime = millis();
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] RX: '%s'\n", headerLine.c_str());
if(headerLine.startsWith("HTTP/1.")) {
if(_canReuse) {
if (headerLine.startsWith(F("HTTP/1."))) {
if (_canReuse) {
_canReuse = (headerLine[sizeof "HTTP/1." - 1] != '0');
}
_returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
} else if(headerLine.indexOf(':')) {
String headerName = headerLine.substring(0, headerLine.indexOf(':'));
String headerValue = headerLine.substring(headerLine.indexOf(':') + 1);
continue;
}
int headerSeparator = headerLine.indexOf(':');
if (headerSeparator > 0) {
String headerName = headerLine.substring(0, headerSeparator);
String headerValue = headerLine.substring(headerSeparator + 1);
headerValue.trim();
if(headerName.equalsIgnoreCase(F("Content-Length"))) {
@ -1324,9 +1337,9 @@ int HTTPClient::handleHeaderResponse()
_location = headerValue;
}
for(size_t i = 0; i < _headerKeysCount; i++) {
if(_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
if (_currentHeaders[i].value != "") {
for (size_t i = 0; i < _headerKeysCount; i++) {
if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
if (!_currentHeaders[i].value.isEmpty()) {
// Existing value, append this one with a comma
_currentHeaders[i].value += ',';
_currentHeaders[i].value += headerValue;
@ -1336,9 +1349,12 @@ int HTTPClient::handleHeaderResponse()
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);
if(_size > 0) {