Skip to content

Commit 5d5200a

Browse files
dirkmuellerdevyte
authored andcommitted
Reduce temporary string creation in HTTPClient::sendHeader (esp8266#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>
1 parent 3197d2a commit 5d5200a

File tree

1 file changed

+51
-35
lines changed

1 file changed

+51
-35
lines changed

libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp

+51-35
Original file line numberDiff line numberDiff line change
@@ -1076,12 +1076,14 @@ String HTTPClient::errorToString(int error)
10761076
void HTTPClient::addHeader(const String& name, const String& value, bool first, bool replace)
10771077
{
10781078
// not allow set of Header handled by code
1079-
if(!name.equalsIgnoreCase(F("Connection")) &&
1080-
!name.equalsIgnoreCase(F("User-Agent")) &&
1081-
!name.equalsIgnoreCase(F("Host")) &&
1082-
!(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())){
1083-
1084-
String headerLine = name;
1079+
if (!name.equalsIgnoreCase(F("Connection")) &&
1080+
!name.equalsIgnoreCase(F("User-Agent")) &&
1081+
!name.equalsIgnoreCase(F("Host")) &&
1082+
!(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())) {
1083+
1084+
String headerLine;
1085+
headerLine.reserve(name.length() + value.length() + 4);
1086+
headerLine += name;
10851087
headerLine += ": ";
10861088

10871089
if (replace) {
@@ -1094,13 +1096,12 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first,
10941096

10951097
headerLine += value;
10961098
headerLine += "\r\n";
1097-
if(first) {
1099+
if (first) {
10981100
_headers = headerLine + _headers;
10991101
} else {
11001102
_headers += headerLine;
11011103
}
11021104
}
1103-
11041105
}
11051106

11061107
void HTTPClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount)
@@ -1225,41 +1226,50 @@ bool HTTPClient::sendHeader(const char * type)
12251226
return false;
12261227
}
12271228

1228-
String header = String(type) + ' ' + (_uri.length() ? _uri : F("/")) + F(" HTTP/1.");
1229+
String header;
1230+
// 128: Arbitrarily chosen to have enough buffer space for avoiding internal reallocations
1231+
header.reserve(_headers.length() + _uri.length() +
1232+
_base64Authorization.length() + _host.length() + _userAgent.length() + 128);
1233+
header += type;
1234+
header += ' ';
1235+
if (_uri.length()) {
1236+
header += _uri;
1237+
} else {
1238+
header += '/';
1239+
}
1240+
header += F(" HTTP/1.");
12291241

12301242
if(_useHTTP10) {
12311243
header += '0';
12321244
} else {
12331245
header += '1';
12341246
}
12351247

1236-
header += String(F("\r\nHost: ")) + _host;
1248+
header += F("\r\nHost: ");
1249+
header += _host;
12371250
if (_port != 80 && _port != 443)
12381251
{
12391252
header += ':';
12401253
header += String(_port);
12411254
}
1242-
header += String(F("\r\nUser-Agent: ")) + _userAgent +
1243-
F("\r\nConnection: ");
1244-
1245-
if(_reuse) {
1246-
header += F("keep-alive");
1247-
} else {
1248-
header += F("close");
1249-
}
1250-
header += "\r\n";
1255+
header += F("\r\nUser-Agent: ");
1256+
header += _userAgent;
12511257

1252-
if(!_useHTTP10) {
1253-
header += F("Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0\r\n");
1258+
if (!_useHTTP10) {
1259+
header += F("\r\nAccept-Encoding: identity;q=1,chunked;q=0.1,*;q=0");
12541260
}
12551261

1256-
if(_base64Authorization.length()) {
1257-
header += F("Authorization: Basic ");
1262+
if (_base64Authorization.length()) {
1263+
header += F("\r\nAuthorization: Basic ");
12581264
header += _base64Authorization;
1259-
header += "\r\n";
12601265
}
12611266

1262-
header += _headers + "\r\n";
1267+
header += F("\r\nConnection: ");
1268+
header += _reuse ? F("keep-alive") : F("close");
1269+
header += "\r\n";
1270+
1271+
header += _headers;
1272+
header += "\r\n";
12631273

12641274
DEBUG_HTTPCLIENT("[HTTP-Client] sending request header\n-----\n%s-----\n", header.c_str());
12651275

@@ -1290,20 +1300,23 @@ int HTTPClient::handleHeaderResponse()
12901300
size_t len = _client->available();
12911301
if(len > 0) {
12921302
String headerLine = _client->readStringUntil('\n');
1293-
headerLine.trim(); // remove \r
12941303

12951304
lastDataTime = millis();
12961305

12971306
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] RX: '%s'\n", headerLine.c_str());
12981307

1299-
if(headerLine.startsWith("HTTP/1.")) {
1300-
if(_canReuse) {
1308+
if (headerLine.startsWith(F("HTTP/1."))) {
1309+
if (_canReuse) {
13011310
_canReuse = (headerLine[sizeof "HTTP/1." - 1] != '0');
13021311
}
13031312
_returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
1304-
} else if(headerLine.indexOf(':')) {
1305-
String headerName = headerLine.substring(0, headerLine.indexOf(':'));
1306-
String headerValue = headerLine.substring(headerLine.indexOf(':') + 1);
1313+
continue;
1314+
}
1315+
1316+
int headerSeparator = headerLine.indexOf(':');
1317+
if (headerSeparator > 0) {
1318+
String headerName = headerLine.substring(0, headerSeparator);
1319+
String headerValue = headerLine.substring(headerSeparator + 1);
13071320
headerValue.trim();
13081321

13091322
if(headerName.equalsIgnoreCase(F("Content-Length"))) {
@@ -1324,9 +1337,9 @@ int HTTPClient::handleHeaderResponse()
13241337
_location = headerValue;
13251338
}
13261339

1327-
for(size_t i = 0; i < _headerKeysCount; i++) {
1328-
if(_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
1329-
if (_currentHeaders[i].value != "") {
1340+
for (size_t i = 0; i < _headerKeysCount; i++) {
1341+
if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
1342+
if (!_currentHeaders[i].value.isEmpty()) {
13301343
// Existing value, append this one with a comma
13311344
_currentHeaders[i].value += ',';
13321345
_currentHeaders[i].value += headerValue;
@@ -1336,9 +1349,12 @@ int HTTPClient::handleHeaderResponse()
13361349
break; // We found a match, stop looking
13371350
}
13381351
}
1352+
continue;
13391353
}
13401354

1341-
if(headerLine == "") {
1355+
headerLine.trim(); // remove \r
1356+
1357+
if (headerLine.isEmpty()) {
13421358
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: %d\n", _returnCode);
13431359

13441360
if(_size > 0) {

0 commit comments

Comments
 (0)