Skip to content

Commit 70ca494

Browse files
committed
add Response header handling
1 parent 95dada1 commit 70ca494

File tree

2 files changed

+164
-17
lines changed

2 files changed

+164
-17
lines changed

libraries/ESP8266httpClient/src/ESP8266httpClient.cpp

Lines changed: 134 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,29 @@
3131
httpClient::httpClient() {
3232
_tcp = NULL;
3333
_tcps = NULL;
34+
35+
_headerKeysCount = 0;
36+
_currentHeaders = NULL;
37+
38+
_returnCode = 0;
39+
_size = 0;
3440
}
3541

3642
httpClient::~httpClient() {
3743
if(connected()) {
3844
_tcp->stop();
3945
}
40-
}
4146

47+
if(_currentHeaders) {
48+
delete[] _currentHeaders;
49+
}
50+
_headerKeysCount = 0;
51+
}
4252

4353
void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) {
4454
_host = host;
4555
_port = port;
46-
_url = url;
56+
_url = url;
4757
_https = https;
4858
_httpsFingerprint = httpsFingerprint;
4959
}
@@ -63,24 +73,32 @@ bool httpClient::connected() {
6373
return false;
6474
}
6575

66-
bool httpClient::GET() {
76+
/**
77+
* send a GET request
78+
* @return http code
79+
*/
80+
int httpClient::GET() {
6781

6882
bool status;
6983
status = connect();
7084
if(status) {
7185
status = sendHeader("GET");
7286
}
7387

74-
return status;
88+
if(status) {
89+
return handleHeaderResponse();
90+
}
91+
92+
return 0;
7593
}
7694

7795
/**
7896
* sends a post request to the server
7997
* @param payload uint8_t *
8098
* @param size size_t
81-
* @return status
99+
* @return http code
82100
*/
83-
bool httpClient::POST(uint8_t * payload, size_t size) {
101+
int httpClient::POST(uint8_t * payload, size_t size) {
84102

85103
bool status;
86104
status = connect();
@@ -93,10 +111,13 @@ bool httpClient::POST(uint8_t * payload, size_t size) {
93111
status = _tcp->write(&payload[0], size);
94112
}
95113

96-
return status;
114+
if(status) {
115+
return handleHeaderResponse();
116+
}
117+
return 0;
97118
}
98119

99-
bool httpClient::POST(String payload) {
120+
int httpClient::POST(String payload) {
100121
return POST((uint8_t *) payload.c_str(), payload.length());
101122
}
102123

@@ -131,6 +152,56 @@ void httpClient::addHeader(const String& name, const String& value, bool first)
131152
}
132153
}
133154

155+
void httpClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
156+
_headerKeysCount = headerKeysCount;
157+
if(_currentHeaders)
158+
delete[] _currentHeaders;
159+
_currentHeaders = new RequestArgument[_headerKeysCount];
160+
for(int i = 0; i < _headerKeysCount; i++) {
161+
_currentHeaders[i].key = headerKeys[i];
162+
}
163+
}
164+
165+
String httpClient::header(const char* name) {
166+
for(int i = 0; i < _headerKeysCount; ++i) {
167+
if(_currentHeaders[i].key == name)
168+
return _currentHeaders[i].value;
169+
}
170+
return String();
171+
}
172+
173+
String httpClient::header(int i) {
174+
if(i < _headerKeysCount)
175+
return _currentHeaders[i].value;
176+
return String();
177+
}
178+
179+
String httpClient::headerName(int i) {
180+
if(i < _headerKeysCount)
181+
return _currentHeaders[i].key;
182+
return String();
183+
}
184+
185+
int httpClient::headers() {
186+
return _headerKeysCount;
187+
}
188+
189+
bool httpClient::hasHeader(const char* name) {
190+
for(int i = 0; i < _headerKeysCount; ++i) {
191+
if((_currentHeaders[i].key == name) && (_currentHeaders[i].value.length() > 0))
192+
return true;
193+
}
194+
return false;
195+
}
196+
197+
/**
198+
* size of message body / payload
199+
* @return 0 if no info or > 0 when Content-Length is set by server
200+
*/
201+
size_t httpClient::getSize(void) {
202+
return _size;
203+
}
204+
134205
/**
135206
* init TCP connection and handle ssl verify if needed
136207
* @return true if connection is ok
@@ -151,7 +222,6 @@ bool httpClient::connect(void) {
151222
_tcp = new WiFiClient();
152223
}
153224

154-
155225
if(!_tcp->connect(_host.c_str(), _port)) {
156226
DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u.\n", _host.c_str(), _port);
157227
return false;
@@ -184,12 +254,64 @@ bool httpClient::connect(void) {
184254
* @return status
185255
*/
186256
bool httpClient::sendHeader(const char * type) {
257+
if(!connected()) {
258+
return false;
259+
}
187260
String header = String(type) + " " + _url + " HTTP/1.1\r\n"
188261
"Host: " + _host + "\r\n"
189262
"User-Agent: ESP8266httpClient\r\n"
190-
"Connection: close\r\n" +
191-
_Headers +
192-
"\r\n";
263+
"Connection: close\r\n" + _Headers + "\r\n";
193264

194265
return _tcp->write(header.c_str(), header.length());
195266
}
267+
268+
/**
269+
* reads the respone from the server
270+
* @return int http code
271+
*/
272+
int httpClient::handleHeaderResponse() {
273+
274+
if(!connected()) {
275+
return false;
276+
}
277+
278+
while(connected()) {
279+
size_t len = _tcp->available();
280+
if(len > 0) {
281+
String headerLine = _tcp->readStringUntil('\n');
282+
headerLine.trim(); // remove \r
283+
284+
DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] RX: '%s'\n", headerLine.c_str());
285+
286+
if(headerLine.startsWith("HTTP/1.")) {
287+
_returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
288+
} else if(headerLine.indexOf(':')) {
289+
String headerName = headerLine.substring(0, headerLine.indexOf(':'));
290+
String headerValue = headerLine.substring(headerLine.indexOf(':') + 2);
291+
292+
if(headerName.equalsIgnoreCase("Content-Length")) {
293+
_size = headerValue.toInt();
294+
}
295+
296+
for(size_t i = 0; i < _headerKeysCount; i++) {
297+
if(_currentHeaders[i].key == headerName) {
298+
_currentHeaders[i].value = headerValue;
299+
return true;
300+
}
301+
}
302+
303+
}
304+
305+
if(headerLine == "") {
306+
DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] code: '%s'\n", String(_returnCode).c_str());
307+
if(_size) {
308+
DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] size: '%s'\n", String(_size).c_str());
309+
}
310+
return _returnCode;
311+
}
312+
313+
} else {
314+
delay(0);
315+
}
316+
}
317+
}

libraries/ESP8266httpClient/src/ESP8266httpClient.h

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,38 @@ class httpClient {
4343

4444
bool connected(void);
4545

46-
bool GET();
47-
bool POST(uint8_t * payload, size_t size);
48-
bool POST(String payload);
46+
/// request handling
47+
int GET();
48+
int POST(uint8_t * payload, size_t size);
49+
int POST(String payload);
4950

5051
void addHeader(const String& name, const String& value, bool first = false);
5152

53+
/// Response handling
54+
void collectHeaders(const char* headerKeys[], const size_t headerKeysCount);
55+
String header(const char* name); // get request header value by name
56+
String header(int i); // get request header value by number
57+
String headerName(int i); // get request header name by number
58+
int headers(); // get header count
59+
bool hasHeader(const char* name); // check if header exists
5260

5361

62+
size_t getSize(void);
63+
5464
WiFiClient & getStream(void);
5565

5666
protected:
67+
68+
struct RequestArgument {
69+
String key;
70+
String value;
71+
};
72+
73+
5774
WiFiClient * _tcp;
5875
WiFiClientSecure * _tcps;
5976

77+
/// request handling
6078
String _host;
6179
uint16_t _port;
6280

@@ -66,10 +84,17 @@ class httpClient {
6684

6785
String _Headers;
6886

69-
bool connect(void);
87+
/// Response handling
88+
RequestArgument* _currentHeaders;
89+
size_t _headerKeysCount;
90+
91+
int _returnCode;
92+
size_t _size;
7093

71-
bool sendHeader(const char * type);
7294

95+
bool connect(void);
96+
bool sendHeader(const char * type);
97+
int handleHeaderResponse();
7398

7499
};
75100

0 commit comments

Comments
 (0)