30
30
31
31
#include " ESP8266HTTPClient.h"
32
32
33
- /* *
34
- * constractor
35
- */
36
- HTTPClient::HTTPClient () {
37
- _tcp = NULL ;
38
- _tcps = NULL ;
33
+ class TransportTraits {
34
+ public:
35
+ virtual std::unique_ptr<WiFiClient> create ()
36
+ {
37
+ return std::unique_ptr<WiFiClient>( new WiFiClient ()) ;
38
+ }
39
39
40
- _port = 0 ;
40
+ virtual bool verify (WiFiClient& client, const char * host)
41
+ {
42
+ return true ;
43
+ }
44
+ };
41
45
42
- _reuse = false ;
43
- _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
44
- _useHTTP10 = false ;
46
+ class TLSTraits : public TransportTraits {
47
+ public:
48
+ TLSTraits (const String& fingerprint) :
49
+ _fingerprint (fingerprint)
50
+ {
51
+ }
45
52
46
- _https = false ;
53
+ std::unique_ptr<WiFiClient> create () override
54
+ {
55
+ return std::unique_ptr<WiFiClient>(new WiFiClientSecure ());
56
+ }
47
57
48
- _userAgent = " ESP8266HTTPClient" ;
58
+ bool verify (WiFiClient& client, const char * host) override
59
+ {
60
+ auto wcs = reinterpret_cast <WiFiClientSecure&>(client);
61
+ return wcs.verify (_fingerprint.c_str (), host);
62
+ }
49
63
50
- _headerKeysCount = 0 ;
51
- _currentHeaders = NULL ;
52
-
53
- _returnCode = 0 ;
54
- _size = -1 ;
55
- _canReuse = false ;
56
- _transferEncoding = HTTPC_TE_IDENTITY;
64
+ protected:
65
+ String _fingerprint;
66
+ };
57
67
68
+ /* *
69
+ * constructor
70
+ */
71
+ HTTPClient::HTTPClient ()
72
+ {
58
73
}
59
74
60
75
/* *
61
- * deconstractor
76
+ * destructor
62
77
*/
63
- HTTPClient::~HTTPClient () {
64
-
65
- if (_tcps) {
66
- _tcps->stop ();
67
- delete _tcps;
68
- _tcps = NULL ;
69
- _tcp = NULL ;
70
- } else if (_tcp) {
78
+ HTTPClient::~HTTPClient ()
79
+ {
80
+ if (_tcp) {
71
81
_tcp->stop ();
72
- delete _tcp;
73
- _tcp = NULL ;
74
82
}
75
-
76
83
if (_currentHeaders) {
77
84
delete[] _currentHeaders;
78
85
}
79
86
}
80
87
81
- /* *
82
- * phasing the url for all needed informations
83
- * @param url String
84
- * @param httpsFingerprint String
85
- */
86
- void HTTPClient::begin (String url, String httpsFingerprint) {
87
88
88
- DEBUG_HTTPCLIENT (" [HTTP-Client][begin] url: %s\n " , url.c_str ());
89
+ bool HTTPClient::begin (String url, String httpsFingerprint) {
90
+ if (httpsFingerprint.length () == 0 ) {
91
+ return false ;
92
+ }
93
+ if (!begin (url)) {
94
+ return false ;
95
+ }
96
+ _transportTraits = TransportTraitsPtr (new TLSTraits (httpsFingerprint));
97
+ DEBUG_HTTPCLIENT (" [HTTP-Client][begin] httpsFingerprint: %s\n " , httpsFingerprint.c_str ());
98
+ return true ;
99
+ }
89
100
90
- _httpsFingerprint = httpsFingerprint;
101
+ void HTTPClient::clear ()
102
+ {
91
103
_returnCode = 0 ;
92
104
_size = -1 ;
105
+ _headers = " " ;
106
+ }
93
107
94
- _Headers = " " ;
95
108
96
- String protocol;
97
- // check for : (http: or https:
98
- int index = url.indexOf (' :' );
99
- // int index2;
109
+ /* *
110
+ * parsing the url for all needed parameters
111
+ * @param url String
112
+ */
113
+ bool HTTPClient::begin (String url)
114
+ {
115
+ DEBUG_HTTPCLIENT (" [HTTP-Client][begin] url: %s\n " , url.c_str ());
100
116
bool hasPort = false ;
101
- if (index >= 0 ) {
102
- protocol = url.substring (0 , index);
103
- url.remove (0 , (index + 3 )); // remove http:// or https://
104
-
105
- index = url.indexOf (' /' );
106
- String host = url.substring (0 , index);
107
- url.remove (0 , index); // remove host part
108
-
109
- // get Authorization
110
- index = host.indexOf (' @' );
111
- if (index >= 0 ) {
112
- // auth info
113
- String auth = host.substring (0 , index);
114
- host.remove (0 , index + 1 ); // remove auth part including @
115
- _base64Authorization = base64::encode (auth);
116
- }
117
+ clear ();
117
118
118
- // get port
119
- index = host.indexOf (' :' );
120
- if (index >= 0 ) {
121
- _host = host.substring (0 , index); // hostname
122
- host.remove (0 , (index + 1 )); // remove hostname + :
123
- _port = host.toInt (); // get port
124
- hasPort = true ;
125
- } else {
126
- _host = host;
127
- }
119
+ // check for : (http: or https:
120
+ int index = url.indexOf (' :' );
121
+ if (index < 0 ) {
122
+ DEBUG_HTTPCLIENT (" [HTTP-Client][begin] failed to parse protocol\n " );
123
+ return false ;
124
+ }
128
125
129
- _url = url;
126
+ _protocol = url.substring (0 , index);
127
+ url.remove (0 , (index + 3 )); // remove http:// or https://
130
128
131
- if (protocol.equalsIgnoreCase (" http" )) {
132
- _https = false ;
133
- if (!hasPort) {
134
- _port = 80 ;
135
- }
136
- } else if (protocol.equalsIgnoreCase (" https" )) {
137
- _https = true ;
138
- if (!hasPort) {
139
- _port = 443 ;
140
- }
141
- } else {
142
- DEBUG_HTTPCLIENT (" [HTTP-Client][begin] protocol: %s unknown?!\n " , protocol.c_str ());
143
- return ;
144
- }
129
+ index = url.indexOf (' /' );
130
+ String host = url.substring (0 , index);
131
+ url.remove (0 , index); // remove host part
145
132
133
+ // get Authorization
134
+ index = host.indexOf (' @' );
135
+ if (index >= 0 ) {
136
+ // auth info
137
+ String auth = host.substring (0 , index);
138
+ host.remove (0 , index + 1 ); // remove auth part including @
139
+ _base64Authorization = base64::encode (auth);
146
140
}
147
141
148
- DEBUG_HTTPCLIENT (" [HTTP-Client][begin] host: %s port: %d url: %s https: %d httpsFingerprint: %s\n " , _host.c_str (), _port, _url.c_str (), _https, _httpsFingerprint.c_str ());
142
+ // get port
143
+ index = host.indexOf (' :' );
144
+ if (index >= 0 ) {
145
+ _host = host.substring (0 , index); // hostname
146
+ host.remove (0 , (index + 1 )); // remove hostname + :
147
+ _port = host.toInt (); // get port
148
+ hasPort = true ;
149
+ } else {
150
+ _host = host;
151
+ }
152
+ _uri = url;
149
153
154
+ if (_protocol.equalsIgnoreCase (" http" )) {
155
+ if (!hasPort) {
156
+ _port = 80 ;
157
+ }
158
+ } else if (_protocol.equalsIgnoreCase (" https" )) {
159
+ if (!hasPort) {
160
+ _port = 443 ;
161
+ }
162
+ } else {
163
+ DEBUG_HTTPCLIENT (" [HTTP-Client][begin] protocol: %s unknown?!\n " , protocol.c_str ());
164
+ return false ;
165
+ }
166
+ _transportTraits = TransportTraitsPtr (new TransportTraits ());
167
+ DEBUG_HTTPCLIENT (" [HTTP-Client][begin] host: %s port: %d url: %s\n " , _host.c_str (), _port, _uri.c_str ());
168
+ return true ;
150
169
}
151
170
152
- void HTTPClient::begin (String host, uint16_t port, String url, bool https, String httpsFingerprint) {
171
+ bool HTTPClient::begin (String host, uint16_t port, String uri)
172
+ {
173
+ clear ();
153
174
_host = host;
154
175
_port = port;
155
- _url = url;
156
- _https = https;
157
- _httpsFingerprint = httpsFingerprint;
176
+ _uri = uri;
177
+ _transportTraits = TransportTraitsPtr (new TransportTraits ());
178
+ DEBUG_HTTPCLIENT (" [HTTP-Client][begin] host: %s port: %d uri: %s\n " , host.c_str (), port, uri.c_str ());
179
+ return true ;
180
+ }
158
181
159
- _returnCode = 0 ;
160
- _size = -1 ;
182
+ bool HTTPClient::begin (String host, uint16_t port, String uri, bool https, String httpsFingerprint)
183
+ {
184
+ if (https) {
185
+ return begin (host, port, uri, httpsFingerprint);
186
+ }
187
+ else {
188
+ return begin (host, port, uri);
189
+ }
190
+ }
161
191
162
- _Headers = " " ;
192
+ bool HTTPClient::begin (String host, uint16_t port, String uri, String httpsFingerprint)
193
+ {
194
+ clear ();
195
+ _host = host;
196
+ _port = port;
197
+ _uri = uri;
163
198
164
- DEBUG_HTTPCLIENT (" [HTTP-Client][begin] host: %s port:%d url: %s https: %d httpsFingerprint: %s\n " , host, port, url, https, httpsFingerprint);
199
+ if (httpsFingerprint.length () == 0 ) {
200
+ return false ;
201
+ }
202
+ _transportTraits = TransportTraitsPtr (new TLSTraits (httpsFingerprint));
203
+ DEBUG_HTTPCLIENT (" [HTTP-Client][begin] host: %s port: %d url: %s httpsFingerprint: %s\n " , host.c_str (), port, uri.c_str (), httpsFingerprint.c_str ());
204
+ return true ;
165
205
}
166
206
167
207
/* *
@@ -469,31 +509,30 @@ int HTTPClient::getSize(void) {
469
509
}
470
510
471
511
/* *
472
- * deprecated Note: this is not working with https!
473
512
* returns the stream of the tcp connection
474
513
* @return WiFiClient
475
514
*/
476
- WiFiClient & HTTPClient::getStream (void ) {
515
+ WiFiClient& HTTPClient::getStream (void ) {
477
516
if (connected ()) {
478
517
return *_tcp;
479
518
}
480
519
481
- DEBUG_HTTPCLIENT (" [HTTP-Client] no stream to return!? \n " );
482
-
483
- // todo return error?
520
+ DEBUG_HTTPCLIENT (" [HTTP-Client] getStream: not connected \n " );
521
+ static WiFiClient empty;
522
+ return empty;
484
523
}
485
524
486
525
/* *
487
526
* returns the stream of the tcp connection
488
527
* @return WiFiClient *
489
528
*/
490
- WiFiClient * HTTPClient::getStreamPtr (void ) {
529
+ WiFiClient* HTTPClient::getStreamPtr (void ) {
491
530
if (connected ()) {
492
- return _tcp;
531
+ return _tcp. get () ;
493
532
}
494
533
495
- DEBUG_HTTPCLIENT (" [HTTP-Client] no stream to return!? \n " );
496
- return NULL ;
534
+ DEBUG_HTTPCLIENT (" [HTTP-Client] getStreamPtr: not connected \n " );
535
+ return nullptr ;
497
536
}
498
537
499
538
/* *
@@ -642,9 +681,9 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first)
642
681
headerLine += " \r\n " ;
643
682
644
683
if (first) {
645
- _Headers = headerLine + _Headers ;
684
+ _headers = headerLine + _headers ;
646
685
} else {
647
- _Headers += headerLine;
686
+ _headers += headerLine;
648
687
}
649
688
}
650
689
@@ -706,39 +745,24 @@ bool HTTPClient::connect(void) {
706
745
return true ;
707
746
}
708
747
709
- if (_https) {
710
- DEBUG_HTTPCLIENT (" [HTTP-Client] connect https...\n " );
711
- if (_tcps) {
712
- delete _tcps;
713
- _tcps = NULL ;
714
- _tcp = NULL ;
715
- }
716
- _tcps = new WiFiClientSecure ();
717
- _tcp = _tcps;
718
- } else {
719
- DEBUG_HTTPCLIENT (" [HTTP-Client] connect http...\n " );
720
- if (_tcp) {
721
- delete _tcp;
722
- _tcp = NULL ;
723
- }
724
- _tcp = new WiFiClient ();
748
+ if (!_transportTraits) {
749
+ DEBUG_HTTPCLIENT (" [HTTP-Client] _transportTraits is null (HTTPClient::begin not called?)\n " );
750
+ return false ;
725
751
}
726
752
753
+ _tcp = _transportTraits->create ();
754
+
727
755
if (!_tcp->connect (_host.c_str (), _port)) {
728
756
DEBUG_HTTPCLIENT (" [HTTP-Client] failed connect to %s:%u\n " , _host.c_str (), _port);
729
757
return false ;
730
758
}
731
759
732
760
DEBUG_HTTPCLIENT (" [HTTP-Client] connected to %s:%u\n " , _host.c_str (), _port);
733
761
734
- if (_https && _httpsFingerprint.length () > 0 ) {
735
- if (_tcps->verify (_httpsFingerprint.c_str (), _host.c_str ())) {
736
- DEBUG_HTTPCLIENT (" [HTTP-Client] https certificate matches\n " );
737
- } else {
738
- DEBUG_HTTPCLIENT (" [HTTP-Client] https certificate doesn't match!\n " );
739
- _tcp->stop ();
740
- return false ;
741
- }
762
+ if (!_transportTraits->verify (*_tcp, _host.c_str ())) {
763
+ DEBUG_HTTPCLIENT (" [HTTP-Client] transport level verify failed\n " );
764
+ _tcp->stop ();
765
+ return false ;
742
766
}
743
767
744
768
// set Timeout for readBytesUntil and readStringUntil
@@ -760,7 +784,7 @@ bool HTTPClient::sendHeader(const char * type) {
760
784
return false ;
761
785
}
762
786
763
- String header = String (type) + " " + _url + " HTTP/1." ;
787
+ String header = String (type) + " " + _uri + " HTTP/1." ;
764
788
765
789
if (_useHTTP10) {
766
790
header += " 0" ;
@@ -788,7 +812,7 @@ bool HTTPClient::sendHeader(const char * type) {
788
812
header += " Authorization: Basic " + _base64Authorization + " \r\n " ;
789
813
}
790
814
791
- header += _Headers + " \r\n " ;
815
+ header += _headers + " \r\n " ;
792
816
793
817
return (_tcp->write (header.c_str (), header.length ()) == header.length ());
794
818
}
0 commit comments