mjuopperi
mjuopperi

Reputation: 971

Arduino C++ move http client initialization to a function

I'm working on an ESP-01 (ESP8266 board) project and making some HTTP requests. I'm trying to refactor my code to keep it DRY, but I'm stuck on how to extract the http client initialization to a function.

Here is my working PUT request function:

void httpPut(const char* url, const char* data) {
  WiFiClient client;
  HTTPClient http;

  http.begin(client, url);
  http.addHeader("Content-Type", "application/json");
  http.PUT(data);

  http.end();
}

My idea was to make a function like this:

HTTPClient prepareRequest(const char* url) {
  WiFiClient client;
  HTTPClient http;

  http.begin(client, url);
  http.addHeader("Content-Type", "application/json");
  return http;
}

And use it in all my request functions like this:

void httpGet(const char* url) {
  HTTPClient http = prepareRequest(url);
  http.GET();
  http.end();
}

I get this compiler error, but I'm not really sure what it means (row 90 mentioned is return http;):

/home/<user>/Code/Micro/mittari-micro/src/mittari.ino: In function 'HTTPClient prepareRequest(const char*)':
/home/<user>/Code/Micro/mittari-micro/src/mittari.ino:90:10: error: use of deleted function 'HTTPClient::HTTPClient(const HTTPClient&)'
   90 |   return http;
      |          ^~~~
In file included from /home/<user>/Code/Micro/mittari-micro/src/mittari.ino:2:
/home/<user>/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h:151:7: note: 'HTTPClient::HTTPClient(const HTTPClient&)' is implicitly deleted because the default definition would be ill-formed:
  151 | class HTTPClient
      |       ^~~~~~~~~~
/home/<user>/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h:151:7: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = StreamString; _Dp = std::default_delete<StreamString>]'
In file included from /home/<user>/.platformio/packages/toolchain-xtensa/xtensa-lx106-elf/include/c++/10.3.0/memory:83,
                 from /home/<user>/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h:28,
                 from /home/<user>/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h:28,
                 from /home/<user>/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h:34,
                 from /home/<user>/Code/Micro/mittari-micro/src/mittari.ino:1:
/home/<user>/.platformio/packages/toolchain-xtensa/xtensa-lx106-elf/include/c++/10.3.0/bits/unique_ptr.h:468:7: note: declared here
  468 |       unique_ptr(const unique_ptr&) = delete;
      |       ^~~~~~~~~~

Is it possible to extract the common functionality to a function and how could I do that?

Upvotes: 0

Views: 549

Answers (2)

mjuopperi
mjuopperi

Reputation: 971

I put the WiFiClient and HTTPClient in global scope and changed the preparation method to void like this:

WiFiClient client;
HTTPClient http;

void prepareRequest(const char* url) {
  http.end(); // In case previous request did not call end for some reason.
  http.begin(client, url);
  http.addHeader("Content-Type", "application/json");
}

void httpGet(const char* url) {
  prepareRequest(url);
  http.GET();
  http.end();
}

It seems to work fine so far.

Upvotes: 0

vnagy
vnagy

Reputation: 1085

You are trying to return a HTTPClient object (http) by value at the end of your prepareRequest function. This would mean copy construction in this case and the compiler is telling you that copy construction is deliberately disabled for this class. (There can be quite a number of reasons for this.)

How it is customary to do this in an Arduino environment is to move your "WiFiClient client" and "HTTPClient http" to global scope. Then write your initialization code into the "setup" function and finally you can use them in whatever functions you like. That way you can separate the setting of the URL and header into the "prepareRequest" function the actual http get into the "httpGet" function without them returning anything.

There are more complicated solutions with const references, pointers, etc... But unless you specifically want to go down that road, I would go for the solution mentioned above.

Upvotes: 2

Related Questions