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