ESPHome  2022.5.1
http_request.cpp
Go to the documentation of this file.
1 #ifdef USE_ARDUINO
2 
3 #include "http_request.h"
4 #include "esphome/core/defines.h"
5 #include "esphome/core/log.h"
7 
8 namespace esphome {
9 namespace http_request {
10 
11 static const char *const TAG = "http_request";
12 
14  ESP_LOGCONFIG(TAG, "HTTP Request:");
15  ESP_LOGCONFIG(TAG, " Timeout: %ums", this->timeout_);
16  ESP_LOGCONFIG(TAG, " User-Agent: %s", this->useragent_);
17  ESP_LOGCONFIG(TAG, " Follow Redirects: %d", this->follow_redirects_);
18  ESP_LOGCONFIG(TAG, " Redirect limit: %d", this->redirect_limit_);
19 }
20 
21 void HttpRequestComponent::set_url(std::string url) {
22  this->url_ = std::move(url);
23  this->secure_ = this->url_.compare(0, 6, "https:") == 0;
24 
25  if (!this->last_url_.empty() && this->url_ != this->last_url_) {
26  // Close connection if url has been changed
27  this->client_.setReuse(false);
28  this->client_.end();
29  }
30  this->client_.setReuse(true);
31 }
32 
33 void HttpRequestComponent::send(const std::vector<HttpRequestResponseTrigger *> &response_triggers) {
34  if (!network::is_connected()) {
35  this->client_.end();
36  this->status_set_warning();
37  ESP_LOGW(TAG, "HTTP Request failed; Not connected to network");
38  return;
39  }
40 
41  bool begin_status = false;
42  const String url = this->url_.c_str();
43 #if defined(USE_ESP32) || (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0))
44 #if defined(USE_ESP32) || USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0)
45  if (this->follow_redirects_) {
46  this->client_.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
47  } else {
48  this->client_.setFollowRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS);
49  }
50 #else
51  this->client_.setFollowRedirects(this->follow_redirects_);
52 #endif
53  this->client_.setRedirectLimit(this->redirect_limit_);
54 #endif
55 #if defined(USE_ESP32)
56  begin_status = this->client_.begin(url);
57 #elif defined(USE_ESP8266)
58  begin_status = this->client_.begin(*this->get_wifi_client_(), url);
59 #endif
60 
61  if (!begin_status) {
62  this->client_.end();
63  this->status_set_warning();
64  ESP_LOGW(TAG, "HTTP Request failed at the begin phase. Please check the configuration");
65  return;
66  }
67 
68  this->client_.setTimeout(this->timeout_);
69  if (this->useragent_ != nullptr) {
70  this->client_.setUserAgent(this->useragent_);
71  }
72  for (const auto &header : this->headers_) {
73  this->client_.addHeader(header.name, header.value, false, true);
74  }
75 
76  int http_code = this->client_.sendRequest(this->method_, this->body_.c_str());
77  for (auto *trigger : response_triggers)
78  trigger->process(http_code);
79 
80  if (http_code < 0) {
81  ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s", this->url_.c_str(),
82  HTTPClient::errorToString(http_code).c_str());
83  this->status_set_warning();
84  return;
85  }
86 
87  if (http_code < 200 || http_code >= 300) {
88  ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Code: %d", this->url_.c_str(), http_code);
89  this->status_set_warning();
90  return;
91  }
92 
93  this->status_clear_warning();
94  ESP_LOGD(TAG, "HTTP Request completed; URL: %s; Code: %d", this->url_.c_str(), http_code);
95 }
96 
97 #ifdef USE_ESP8266
98 std::shared_ptr<WiFiClient> HttpRequestComponent::get_wifi_client_() {
99 #ifdef USE_HTTP_REQUEST_ESP8266_HTTPS
100  if (this->secure_) {
101  if (this->wifi_client_secure_ == nullptr) {
102  this->wifi_client_secure_ = std::make_shared<BearSSL::WiFiClientSecure>();
103  this->wifi_client_secure_->setInsecure();
104  this->wifi_client_secure_->setBufferSizes(512, 512);
105  }
106  return this->wifi_client_secure_;
107  }
108 #endif
109 
110  if (this->wifi_client_ == nullptr) {
111  this->wifi_client_ = std::make_shared<WiFiClient>();
112  }
113  return this->wifi_client_;
114 }
115 #endif
116 
118  this->last_url_ = this->url_;
119  this->client_.end();
120 }
121 
123 #if defined(ESP32)
124  // The static variable is here because HTTPClient::getString() returns a String on ESP32,
125  // and we need something to keep a buffer alive.
126  static String str;
127 #else
128  // However on ESP8266, HTTPClient::getString() returns a String& to a member variable.
129  // Leaving this the default so that any new platform either doesn't copy, or encounters a compilation error.
130  auto &
131 #endif
132  str = this->client_.getString();
133  return str.c_str();
134 }
135 
136 } // namespace http_request
137 } // namespace esphome
138 
139 #endif // USE_ARDUINO
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
Definition: util.cpp:15
std::shared_ptr< BearSSL::WiFiClientSecure > wifi_client_secure_
Definition: http_request.h:66
void status_clear_warning()
Definition: component.cpp:148
void send(const std::vector< HttpRequestResponseTrigger *> &response_triggers)
void status_set_warning()
Definition: component.cpp:140
std::shared_ptr< WiFiClient > get_wifi_client_()
Definition: a4988.cpp:4
std::shared_ptr< WiFiClient > wifi_client_
Definition: http_request.h:64