Chris Dzombak

Reusing an ESP8266HTTPClient

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: