1+
2+ #include " HTTPService.h"
3+ #include " Platform.h"
4+ #include " Version.h"
5+
6+ // Uncomment bellow in case of a problem and rebuild sketch
7+ // #define INFLUXDB_CLIENT_DEBUG_ENABLE
8+ #include " util/debug.h"
9+
10+ static const char UserAgent[] PROGMEM = " influxdb-client-arduino/" INFLUXDB_CLIENT_VERSION " (" INFLUXDB_CLIENT_PLATFORM " " INFLUXDB_CLIENT_PLATFORM_VERSION " )" ;
11+
12+ #if defined(ESP8266)
13+ bool checkMFLN (BearSSL::WiFiClientSecure *client, String url);
14+ #endif
15+
16+ // This cannot be put to PROGMEM due to the way how it is used
17+ static const char *RetryAfter = " Retry-After" ;
18+ const char *TransferEncoding = " Transfer-Encoding" ;
19+
20+ HTTPService::HTTPService (const String &serverUrl, const String &authToken, const char *certInfo, bool insecure) {
21+ _authToken = authToken;
22+ _apiURL = serverUrl;
23+ _apiURL += " /api/v2/" ;
24+ bool https = serverUrl.startsWith (" https" );
25+ if (https) {
26+ #if defined(ESP8266)
27+ BearSSL::WiFiClientSecure *wifiClientSec = new BearSSL::WiFiClientSecure;
28+ if (insecure) {
29+ wifiClientSec->setInsecure ();
30+ } else if (certInfo && strlen_P (certInfo) > 0 ) {
31+ if (strlen_P (certInfo) > 60 ) { // differentiate fingerprint and cert
32+ _cert = new BearSSL::X509List (certInfo);
33+ wifiClientSec->setTrustAnchors (_cert);
34+ } else {
35+ wifiClientSec->setFingerprint (certInfo);
36+ }
37+ }
38+ checkMFLN (wifiClientSec, serverUrl);
39+ #elif defined(ESP32)
40+ WiFiClientSecure *wifiClientSec = new WiFiClientSecure;
41+ if (insecure) {
42+ #ifndef ARDUINO_ESP32_RELEASE_1_0_4
43+ // This works only in ESP32 SDK 1.0.5 and higher
44+ wifiClientSec->setInsecure ();
45+ #endif
46+ } else if (_certInfo && strlen_P (certInfo) > 0 ) {
47+ wifiClientSec->setCACert (certInfo);
48+ }
49+ #endif
50+ _wifiClient = wifiClientSec;
51+ } else {
52+ _wifiClient = new WiFiClient;
53+ }
54+ if (!_httpClient) {
55+ _httpClient = new HTTPClient;
56+ }
57+ _httpClient->setReuse (_httpOptions._connectionReuse );
58+
59+ _httpClient->setUserAgent (FPSTR (UserAgent));
60+ };
61+
62+ HTTPService::~HTTPService () {
63+ if (_httpClient) {
64+ delete _httpClient;
65+ _httpClient = nullptr ;
66+ }
67+ if (_wifiClient) {
68+ delete _wifiClient;
69+ _wifiClient = nullptr ;
70+ }
71+ #if defined(ESP8266)
72+ if (_cert) {
73+ delete _cert;
74+ _cert = nullptr ;
75+ }
76+ #endif
77+ _lastStatusCode = 0 ;
78+ _lastErrorResponse = " " ;
79+ }
80+
81+
82+ void HTTPService::setHTTPOptions (const HTTPOptions & httpOptions) {
83+ _httpOptions = httpOptions;
84+ if (!_httpClient) {
85+ _httpClient = new HTTPClient;
86+ }
87+ _httpClient->setReuse (_httpOptions._connectionReuse );
88+ _httpClient->setTimeout (_httpOptions._httpReadTimeout );
89+ #if defined(ESP32)
90+ _httpClient->setConnectTimeout (_httpOptions._httpReadTimeout );
91+ #endif
92+ }
93+
94+ // parse URL for host and port and call probeMaxFragmentLength
95+ #if defined(ESP8266)
96+ bool checkMFLN (BearSSL::WiFiClientSecure *client, String url) {
97+ int index = url.indexOf (' :' );
98+ if (index < 0 ) {
99+ return false ;
100+ }
101+ String protocol = url.substring (0 , index);
102+ int port = -1 ;
103+ url.remove (0 , (index + 3 )); // remove http:// or https://
104+
105+ if (protocol == " http" ) {
106+ // set default port for 'http'
107+ port = 80 ;
108+ } else if (protocol == " https" ) {
109+ // set default port for 'https'
110+ port = 443 ;
111+ } else {
112+ return false ;
113+ }
114+ index = url.indexOf (' /' );
115+ String host = url.substring (0 , index);
116+ url.remove (0 , index); // remove host
117+ // check Authorization
118+ index = host.indexOf (' @' );
119+ if (index >= 0 ) {
120+ host.remove (0 , index + 1 ); // remove auth part including @
121+ }
122+ // get port
123+ index = host.indexOf (' :' );
124+ if (index >= 0 ) {
125+ String portS = host;
126+ host = host.substring (0 , index); // hostname
127+ portS.remove (0 , (index + 1 )); // remove hostname + :
128+ port = portS.toInt (); // get port
129+ }
130+ INFLUXDB_CLIENT_DEBUG (" [D] probeMaxFragmentLength to %s:%d\n " , host.c_str (), port);
131+ bool mfln = client->probeMaxFragmentLength (host, port, 1024 );
132+ INFLUXDB_CLIENT_DEBUG (" [D] MFLN:%s\n " , mfln ? " yes" : " no" );
133+ if (mfln) {
134+ client->setBufferSizes (1024 , 1024 );
135+ }
136+ return mfln;
137+ }
138+ #endif // ESP8266
139+
140+ bool HTTPService::beforeRequest (const char *url) {
141+ if (!_httpClient->begin (*_wifiClient, url)) {
142+ _lastErrorResponse = F (" begin failed" );
143+ return false ;
144+ }
145+ if (_authToken.length () > 0 ) {
146+ _httpClient->addHeader (F (" Authorization" ), " Token " + _authToken);
147+ }
148+ const char * headerKeys[] = {RetryAfter, TransferEncoding} ;
149+ _httpClient->collectHeaders (headerKeys, 2 );
150+ return true ;
151+ }
152+
153+ bool HTTPService::doPOST (const char *url, const char *data, const char *contentType, int expectedCode, httpResponseCallback cb) {
154+ INFLUXDB_CLIENT_DEBUG (" [D] POST request - %s, data: %dbytes, type %s\n " , url, strlen (data), contentType);
155+ if (!beforeRequest (url)) {
156+ return false ;
157+ }
158+ if (contentType) {
159+ _httpClient->addHeader (F (" Content-Type" ), FPSTR (contentType));
160+ }
161+ _lastStatusCode = _httpClient->POST ((uint8_t *) data, strlen (data));
162+ return afterRequest (expectedCode, cb);
163+ }
164+
165+ bool HTTPService::doGET (const char *url, int expectedCode, httpResponseCallback cb) {
166+ INFLUXDB_CLIENT_DEBUG (" [D] GET request - %s\n " , url);
167+ if (!beforeRequest (url)) {
168+ return false ;
169+ }
170+ _lastStatusCode = _httpClient->GET ();
171+ return afterRequest (expectedCode, cb, false );
172+ }
173+
174+ bool HTTPService::afterRequest (int expectedStatusCode, httpResponseCallback cb, bool modifyLastConnStatus) {
175+ if (modifyLastConnStatus) {
176+ _lastRequestTime = millis ();
177+ INFLUXDB_CLIENT_DEBUG (" [D] HTTP status code - %d\n " , _lastStatusCode);
178+ _lastRetryAfter = 0 ;
179+ if (_lastStatusCode >= 429 ) { // retryable server errors
180+ if (_httpClient->hasHeader (RetryAfter)) {
181+ _lastRetryAfter = _httpClient->header (RetryAfter).toInt ();
182+ INFLUXDB_CLIENT_DEBUG (" [D] Reply after - %d\n " , _lastRetryAfter);
183+ }
184+ }
185+ }
186+ _lastErrorResponse = " " ;
187+ bool ret = _lastStatusCode == expectedStatusCode;
188+ bool endConnection = true ;
189+ if (!ret) {
190+ if (_lastStatusCode > 0 ) {
191+ _lastErrorResponse = _httpClient->getString ();
192+ INFLUXDB_CLIENT_DEBUG (" [D] Response:\n %s\n " , _lastErrorResponse.c_str ());
193+ } else {
194+ _lastErrorResponse = _httpClient->errorToString (_lastStatusCode);
195+ INFLUXDB_CLIENT_DEBUG (" [E] Error - %s\n " , _lastErrorResponse.c_str ());
196+ }
197+ } else if (cb){
198+ endConnection = cb (_httpClient);
199+ }
200+ if (endConnection) {
201+ _httpClient->end ();
202+ }
203+ return ret;
204+ }
0 commit comments