Skip to content

Commit 14949f5

Browse files
committed
Merge pull request #1091 from Links2004/httpClient
rework ESP8266HTTPUpdate to use httpClient and allow https updates
2 parents 04e5623 + ceb8acb commit 14949f5

File tree

6 files changed

+274
-95
lines changed

6 files changed

+274
-95
lines changed

doc/ota_updates/ota_updates.md

+1
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ function sendFile($path) {
340340
header('Content-Type: application/octet-stream', true);
341341
header('Content-Disposition: attachment; filename='.basename($path));
342342
header('Content-Length: '.filesize($path), true);
343+
header('x-MD5: '.md5_file($path), true);
343344
readfile($path);
344345
}
345346

libraries/ESP8266httpClient/src/ESP8266httpClient.cpp

+98-15
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ httpClient::httpClient() {
4141
_reuse = false;
4242
_https = false;
4343

44+
_userAgent = "ESP8266httpClient";
45+
4446
_headerKeysCount = 0;
4547
_currentHeaders = NULL;
4648

@@ -77,7 +79,7 @@ httpClient::~httpClient() {
7779
* @param httpsFingerprint const char *
7880
*/
7981
void httpClient::begin(const char *url, const char * httpsFingerprint) {
80-
begin(String(url), String(httpsFingerprint));
82+
begin(String(url), String(httpsFingerprint));
8183
}
8284

8385
/**
@@ -111,7 +113,7 @@ void httpClient::begin(String url, String httpsFingerprint) {
111113
_host = url.substring(0, index); // hostname
112114
url.remove(0, (index + 1)); // remove hostname + :
113115

114-
index = url.indexOf('/');
116+
index = url.indexOf('/');
115117
_port = url.substring(0, index).toInt(); // get port
116118
url.remove(0, index); // remove port
117119
hasPort = true;
@@ -200,7 +202,6 @@ bool httpClient::connected() {
200202
return false;
201203
}
202204

203-
204205
/**
205206
* try to reuse the connection to the server
206207
* keep-alive
@@ -210,6 +211,14 @@ void httpClient::setReuse(bool reuse) {
210211
_reuse = reuse;
211212
}
212213

214+
/**
215+
* set User Agent
216+
* @param userAgent const char *
217+
*/
218+
void httpClient::setUserAgent(const char * userAgent) {
219+
_userAgent = userAgent;
220+
}
221+
213222
/**
214223
* send a GET request
215224
* @return http code
@@ -240,7 +249,7 @@ int httpClient::POST(String payload) {
240249
* @return -1 if no info or > 0 when Content-Length is set by server
241250
*/
242251
int httpClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
243-
// connect ro server
252+
// connect to server
244253
if(!connect()) {
245254
return HTTPC_ERROR_CONNECTION_REFUSED;
246255
}
@@ -265,6 +274,77 @@ int httpClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
265274
return handleHeaderResponse();
266275
}
267276

277+
/**
278+
* sendRequest
279+
* @param type const char * "GET", "POST", ....
280+
* @param stream Stream * data stream for the message body
281+
* @param size size_t size for the message body if 0 not Content-Length is send
282+
* @return -1 if no info or > 0 when Content-Length is set by server
283+
*/
284+
int httpClient::sendRequest(const char * type, Stream * stream, size_t size) {
285+
286+
if(!stream) {
287+
return HTTPC_ERROR_NO_STREAM;
288+
}
289+
290+
// connect to server
291+
if(!connect()) {
292+
return HTTPC_ERROR_CONNECTION_REFUSED;
293+
}
294+
295+
if(size > 0) {
296+
addHeader("Content-Length", String(size));
297+
}
298+
299+
// send Header
300+
if(!sendHeader(type)) {
301+
return HTTPC_ERROR_SEND_HEADER_FAILED;
302+
}
303+
304+
// create buffer for read
305+
uint8_t buff[1460] = { 0 };
306+
307+
int len = size;
308+
int bytesWritten = 0;
309+
310+
if(len == 0) {
311+
len = -1;
312+
}
313+
314+
// read all data from stream and send it to server
315+
while(connected() && stream->available() && (len > 0 || len == -1)) {
316+
317+
// get available data size
318+
size_t s = stream->available();
319+
320+
if(s) {
321+
int c = stream->readBytes(buff, ((s > sizeof(buff)) ? sizeof(buff) : s));
322+
323+
// write it to Stream
324+
bytesWritten += _tcp->write((const uint8_t *)buff, c);
325+
326+
if(len > 0) {
327+
len -= c;
328+
}
329+
330+
delay(0);
331+
} else {
332+
delay(1);
333+
}
334+
}
335+
336+
if(size && (int)size != bytesWritten) {
337+
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, _size);
338+
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!");
339+
return HTTPC_ERROR_SEND_PAYLOAD_FAILED;
340+
} else {
341+
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload written: %d\n", bytesWritten);
342+
}
343+
344+
// handle Server Response (Header)
345+
return handleHeaderResponse();
346+
}
347+
268348
/**
269349
* size of message body / payload
270350
* @return -1 if no info or > 0 when Content-Length is set by server
@@ -374,7 +454,6 @@ String httpClient::getString(void) {
374454
return sstring;
375455
}
376456

377-
378457
/**
379458
* adds Header to the request
380459
* @param name
@@ -383,16 +462,20 @@ String httpClient::getString(void) {
383462
*/
384463
void httpClient::addHeader(const String& name, const String& value, bool first) {
385464

386-
String headerLine = name;
387-
headerLine += ": ";
388-
headerLine += value;
389-
headerLine += "\r\n";
465+
// not allow set of Header handled by code
466+
if(!name.equalsIgnoreCase("Connection") && !name.equalsIgnoreCase("User-Agent") && !name.equalsIgnoreCase("Host")) {
467+
String headerLine = name;
468+
headerLine += ": ";
469+
headerLine += value;
470+
headerLine += "\r\n";
390471

391-
if(first) {
392-
_Headers = headerLine + _Headers;
393-
} else {
394-
_Headers += headerLine;
472+
if(first) {
473+
_Headers = headerLine + _Headers;
474+
} else {
475+
_Headers += headerLine;
476+
}
395477
}
478+
396479
}
397480

398481
void httpClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
@@ -448,7 +531,6 @@ bool httpClient::connect(void) {
448531
return true;
449532
}
450533

451-
452534
if(_https) {
453535
DEBUG_HTTPCLIENT("[HTTP-Client] connect https...\n");
454536
if(_tcps) {
@@ -502,9 +584,10 @@ bool httpClient::sendHeader(const char * type) {
502584
if(!connected()) {
503585
return false;
504586
}
587+
505588
String header = String(type) + " " + _url + " HTTP/1.1\r\n"
506589
"Host: " + _host + "\r\n"
507-
"User-Agent: ESP8266httpClient\r\n"
590+
"User-Agent: " + _userAgent + "\r\n"
508591
"Connection: ";
509592

510593
if(_reuse) {

libraries/ESP8266httpClient/src/ESP8266httpClient.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,14 @@ class httpClient {
5959
bool connected(void);
6060

6161
void setReuse(bool reuse); /// keep-alive
62+
void setUserAgent(const char * userAgent);
6263

6364
/// request handling
6465
int GET();
6566
int POST(uint8_t * payload, size_t size);
6667
int POST(String payload);
6768
int sendRequest(const char * type, uint8_t * payload = NULL, size_t size = 0);
69+
int sendRequest(const char * type, Stream * stream, size_t size = 0);
6870

6971
void addHeader(const String& name, const String& value, bool first = false);
7072

@@ -105,7 +107,8 @@ class httpClient {
105107
bool _https;
106108
String _httpsFingerprint;
107109

108-
String _Headers;
110+
String _Headers;
111+
String _userAgent;
109112

110113
/// Response handling
111114
RequestArgument* _currentHeaders;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* httpUpdate.ino
3+
*
4+
* Created on: 27.11.2015
5+
*
6+
*/
7+
8+
#include <Arduino.h>
9+
10+
#include <ESP8266WiFi.h>
11+
#include <ESP8266WiFiMulti.h>
12+
13+
#include <ESP8266httpClient.h>
14+
#include <ESP8266httpUpdate.h>
15+
16+
#define USE_SERIAL Serial
17+
18+
ESP8266WiFiMulti WiFiMulti;
19+
20+
void setup() {
21+
22+
USE_SERIAL.begin(115200);
23+
// USE_SERIAL.setDebugOutput(true);
24+
25+
USE_SERIAL.println();
26+
USE_SERIAL.println();
27+
USE_SERIAL.println();
28+
29+
for(uint8_t t = 4; t > 0; t--) {
30+
USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
31+
USE_SERIAL.flush();
32+
delay(1000);
33+
}
34+
35+
WiFiMulti.addAP("SSID", "PASSWORD");
36+
37+
}
38+
39+
void loop() {
40+
// wait for WiFi connection
41+
if((WiFiMulti.run() == WL_CONNECTED)) {
42+
43+
t_httpUpdate_return ret = ESPhttpUpdate.update("http://server/file.bin");
44+
//t_httpUpdate_return ret = ESPhttpUpdate.update("https://server/file.bin");
45+
46+
switch(ret) {
47+
case HTTP_UPDATE_FAILED:
48+
USE_SERIAL.println("HTTP_UPDATE_FAILD");
49+
break;
50+
51+
case HTTP_UPDATE_NO_UPDATES:
52+
USE_SERIAL.println("HTTP_UPDATE_NO_UPDATES");
53+
break;
54+
55+
case HTTP_UPDATE_OK:
56+
USE_SERIAL.println("HTTP_UPDATE_OK");
57+
break;
58+
}
59+
}
60+
}
61+

0 commit comments

Comments
 (0)