Reusing an ESP8266HTTPClient
Part of the Getting Started with ESP8266 + Arduino series.
In my ESP8266/Arduino/PlatformIO HTTPS demo project, I make two consecutive HTTPS requests, to different sites, from the same function. You can see the code in question here.
I’m doing this work using the ESP8266HTTPClient library, which is part of the Arduino core for ESP8266.
For the second request, I wanted to reuse the HTTP client instance from the first request. This should help me conserve RAM in this resource-constrained environment. The library includes an example that covers reusing a client, so I figured that would be easy.
Alas, my second HTTPS request always returned a 404 status code, even though I am confident the URL is valid:
5911: Starting GET request to https://ip.dzdz.cz
7251: HTTP 200
73.145.176.71
7274: Starting POST request to https://hookb.in/nPpMqzWewdtZ7Qrr7gYB
7485: HTTP Error 404
Enabling debug output from the library helped … somewhat. Let’s take a look:
This bug took me a while to figure out; after all, looking at lines 30-31 above, it seems like the HTTP client is talking to the correct host. But, look at line 34:
[HTTP-Client] connect: already connected, reusing connection
This is nonsensical, since the client has never talked to this host before. And yet, the rest of the debug log output looks reasonable.
Digging into the library’s code, I see some relatively complex state management around connection reuse. Based on a quick search through the implementation, I can see that this reusing connection
log message happens immediately after a check of the _reuse
and _canReuse
instance variables. Working with my IDE’s “Find Usages” feature, I can see that these variables are only written to by a few code paths. Notably, none of them is invoked by the end()
method I call to finish the first request or by the begin(…)
method I call to setup the second request.
This means that, though the HTTP client logs that it’s sending the request to the correct URL, it’s actually reusing the connection made for the first request. The client therefore sends the request to the wrong server.
The _reuse
variable can be set with the setReuse(bool)
method. Sure enough, adding a call to that method fixes my problem 🎉
36175: Starting GET request to https://ip.dzdz.cz
37399: HTTP 200
73.145.176.71
37401: Starting POST request to https://hookb.in/nPpMqzWewdtZ7Qrr7gYB
39259: HTTP 200
I haven’t taken the time to fully grok ESP8266HTTPClient’s connection reuse state management, but I’m pretty sure this reflects a bug. _canReuse
is cleared by the setURL(…)
method, but that seems to be called only when handling an HTTP redirect. I’d expect the begin(…)
codepath to perform a similar check (perhaps it should use setURL(…)
internally?) and clear _canReuse
when necessary.
But, in the mean time, that’s how you reuse an ESP8266HTTPClient: call client.setReuse(false)
.
I’ve filed a bug for this in the ESP8266 Arduino core project: #8331.
Previous posts in this series & related resources:
- How to enable debug logging for Arduino’s ESP8266HTTPClient with PlatformIO (October 8, 2021)
- ESP8266 + PlatformIO Serial Console Monitoring with Exception Decoding (October 7, 2021)
- Debugging an Intermittent Arduino/ESP8266 ISR Crash (October 7, 2021)
- ESP8266HTTPClient header
- ESP8266HTTPClient implementation
- ESP8266HTTPClient Connection Reuse Example