3030
3131#include " ESP8266HTTPClient.h"
3232
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+ }
3939
40- _port = 0 ;
40+ virtual bool verify (WiFiClient& client, const char * host)
41+ {
42+ return true ;
43+ }
44+ };
4145
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+ }
4552
46- _https = false ;
53+ std::unique_ptr<WiFiClient> create () override
54+ {
55+ return std::unique_ptr<WiFiClient>(new WiFiClientSecure ());
56+ }
4757
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+ }
4963
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+ };
5767
68+ /* *
69+ * constructor
70+ */
71+ HTTPClient::HTTPClient ()
72+ {
5873}
5974
6075/* *
61- * deconstractor
76+ * destructor
6277 */
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) {
7181 _tcp->stop ();
72- delete _tcp;
73- _tcp = NULL ;
7482 }
75-
7683 if (_currentHeaders) {
7784 delete[] _currentHeaders;
7885 }
7986}
8087
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) {
8788
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+ }
89100
90- _httpsFingerprint = httpsFingerprint;
101+ void HTTPClient::clear ()
102+ {
91103 _returnCode = 0 ;
92104 _size = -1 ;
105+ _headers = " " ;
106+ }
93107
94- _Headers = " " ;
95108
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 ());
100116 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 ();
117118
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+ }
128125
129- _url = url;
126+ _protocol = url.substring (0 , index);
127+ url.remove (0 , (index + 3 )); // remove http:// or https://
130128
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
145132
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);
146140 }
147141
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;
149153
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 ;
150169}
151170
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 ();
153174 _host = host;
154175 _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+ }
158181
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+ }
161191
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;
163198
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 ;
165205}
166206
167207/* *
@@ -469,31 +509,30 @@ int HTTPClient::getSize(void) {
469509}
470510
471511/* *
472- * deprecated Note: this is not working with https!
473512 * returns the stream of the tcp connection
474513 * @return WiFiClient
475514 */
476- WiFiClient & HTTPClient::getStream (void ) {
515+ WiFiClient& HTTPClient::getStream (void ) {
477516 if (connected ()) {
478517 return *_tcp;
479518 }
480519
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;
484523}
485524
486525/* *
487526 * returns the stream of the tcp connection
488527 * @return WiFiClient *
489528 */
490- WiFiClient * HTTPClient::getStreamPtr (void ) {
529+ WiFiClient* HTTPClient::getStreamPtr (void ) {
491530 if (connected ()) {
492- return _tcp;
531+ return _tcp. get () ;
493532 }
494533
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 ;
497536}
498537
499538/* *
@@ -642,9 +681,9 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first)
642681 headerLine += " \r\n " ;
643682
644683 if (first) {
645- _Headers = headerLine + _Headers ;
684+ _headers = headerLine + _headers ;
646685 } else {
647- _Headers += headerLine;
686+ _headers += headerLine;
648687 }
649688 }
650689
@@ -706,39 +745,24 @@ bool HTTPClient::connect(void) {
706745 return true ;
707746 }
708747
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 ;
725751 }
726752
753+ _tcp = _transportTraits->create ();
754+
727755 if (!_tcp->connect (_host.c_str (), _port)) {
728756 DEBUG_HTTPCLIENT (" [HTTP-Client] failed connect to %s:%u\n " , _host.c_str (), _port);
729757 return false ;
730758 }
731759
732760 DEBUG_HTTPCLIENT (" [HTTP-Client] connected to %s:%u\n " , _host.c_str (), _port);
733761
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 ;
742766 }
743767
744768 // set Timeout for readBytesUntil and readStringUntil
@@ -760,7 +784,7 @@ bool HTTPClient::sendHeader(const char * type) {
760784 return false ;
761785 }
762786
763- String header = String (type) + " " + _url + " HTTP/1." ;
787+ String header = String (type) + " " + _uri + " HTTP/1." ;
764788
765789 if (_useHTTP10) {
766790 header += " 0" ;
@@ -788,7 +812,7 @@ bool HTTPClient::sendHeader(const char * type) {
788812 header += " Authorization: Basic " + _base64Authorization + " \r\n " ;
789813 }
790814
791- header += _Headers + " \r\n " ;
815+ header += _headers + " \r\n " ;
792816
793817 return (_tcp->write (header.c_str (), header.length ()) == header.length ());
794818}
0 commit comments