Part of the Getting Started with ESP8266 + Arduino series.
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 22.214.171.124 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
_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.
_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 126.96.36.199 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
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