1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-21 21:22:31 +03:00

add Response header handling

This commit is contained in:
Markus Sattler
2015-11-17 17:40:14 +01:00
parent 95dada180c
commit 70ca494a7f
2 changed files with 164 additions and 17 deletions

View File

@ -31,19 +31,29 @@
httpClient::httpClient() { httpClient::httpClient() {
_tcp = NULL; _tcp = NULL;
_tcps = NULL; _tcps = NULL;
_headerKeysCount = 0;
_currentHeaders = NULL;
_returnCode = 0;
_size = 0;
} }
httpClient::~httpClient() { httpClient::~httpClient() {
if(connected()) { if(connected()) {
_tcp->stop(); _tcp->stop();
} }
}
if(_currentHeaders) {
delete[] _currentHeaders;
}
_headerKeysCount = 0;
}
void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) { void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) {
_host = host; _host = host;
_port = port; _port = port;
_url = url; _url = url;
_https = https; _https = https;
_httpsFingerprint = httpsFingerprint; _httpsFingerprint = httpsFingerprint;
} }
@ -63,7 +73,11 @@ bool httpClient::connected() {
return false; return false;
} }
bool httpClient::GET() { /**
* send a GET request
* @return http code
*/
int httpClient::GET() {
bool status; bool status;
status = connect(); status = connect();
@ -71,16 +85,20 @@ bool httpClient::GET() {
status = sendHeader("GET"); status = sendHeader("GET");
} }
return status; if(status) {
return handleHeaderResponse();
}
return 0;
} }
/** /**
* sends a post request to the server * sends a post request to the server
* @param payload uint8_t * * @param payload uint8_t *
* @param size size_t * @param size size_t
* @return status * @return http code
*/ */
bool httpClient::POST(uint8_t * payload, size_t size) { int httpClient::POST(uint8_t * payload, size_t size) {
bool status; bool status;
status = connect(); status = connect();
@ -93,10 +111,13 @@ bool httpClient::POST(uint8_t * payload, size_t size) {
status = _tcp->write(&payload[0], size); status = _tcp->write(&payload[0], size);
} }
return status; if(status) {
return handleHeaderResponse();
}
return 0;
} }
bool httpClient::POST(String payload) { int httpClient::POST(String payload) {
return POST((uint8_t *) payload.c_str(), payload.length()); return POST((uint8_t *) payload.c_str(), payload.length());
} }
@ -131,6 +152,56 @@ void httpClient::addHeader(const String& name, const String& value, bool first)
} }
} }
void httpClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
_headerKeysCount = headerKeysCount;
if(_currentHeaders)
delete[] _currentHeaders;
_currentHeaders = new RequestArgument[_headerKeysCount];
for(int i = 0; i < _headerKeysCount; i++) {
_currentHeaders[i].key = headerKeys[i];
}
}
String httpClient::header(const char* name) {
for(int i = 0; i < _headerKeysCount; ++i) {
if(_currentHeaders[i].key == name)
return _currentHeaders[i].value;
}
return String();
}
String httpClient::header(int i) {
if(i < _headerKeysCount)
return _currentHeaders[i].value;
return String();
}
String httpClient::headerName(int i) {
if(i < _headerKeysCount)
return _currentHeaders[i].key;
return String();
}
int httpClient::headers() {
return _headerKeysCount;
}
bool httpClient::hasHeader(const char* name) {
for(int i = 0; i < _headerKeysCount; ++i) {
if((_currentHeaders[i].key == name) && (_currentHeaders[i].value.length() > 0))
return true;
}
return false;
}
/**
* size of message body / payload
* @return 0 if no info or > 0 when Content-Length is set by server
*/
size_t httpClient::getSize(void) {
return _size;
}
/** /**
* init TCP connection and handle ssl verify if needed * init TCP connection and handle ssl verify if needed
* @return true if connection is ok * @return true if connection is ok
@ -151,7 +222,6 @@ bool httpClient::connect(void) {
_tcp = new WiFiClient(); _tcp = new WiFiClient();
} }
if(!_tcp->connect(_host.c_str(), _port)) { if(!_tcp->connect(_host.c_str(), _port)) {
DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u.\n", _host.c_str(), _port); DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u.\n", _host.c_str(), _port);
return false; return false;
@ -184,12 +254,64 @@ bool httpClient::connect(void) {
* @return status * @return status
*/ */
bool httpClient::sendHeader(const char * type) { bool httpClient::sendHeader(const char * type) {
if(!connected()) {
return false;
}
String header = String(type) + " " + _url + " HTTP/1.1\r\n" String header = String(type) + " " + _url + " HTTP/1.1\r\n"
"Host: " + _host + "\r\n" "Host: " + _host + "\r\n"
"User-Agent: ESP8266httpClient\r\n" "User-Agent: ESP8266httpClient\r\n"
"Connection: close\r\n" + "Connection: close\r\n" + _Headers + "\r\n";
_Headers +
"\r\n";
return _tcp->write(header.c_str(), header.length()); return _tcp->write(header.c_str(), header.length());
} }
/**
* reads the respone from the server
* @return int http code
*/
int httpClient::handleHeaderResponse() {
if(!connected()) {
return false;
}
while(connected()) {
size_t len = _tcp->available();
if(len > 0) {
String headerLine = _tcp->readStringUntil('\n');
headerLine.trim(); // remove \r
DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] RX: '%s'\n", headerLine.c_str());
if(headerLine.startsWith("HTTP/1.")) {
_returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
} else if(headerLine.indexOf(':')) {
String headerName = headerLine.substring(0, headerLine.indexOf(':'));
String headerValue = headerLine.substring(headerLine.indexOf(':') + 2);
if(headerName.equalsIgnoreCase("Content-Length")) {
_size = headerValue.toInt();
}
for(size_t i = 0; i < _headerKeysCount; i++) {
if(_currentHeaders[i].key == headerName) {
_currentHeaders[i].value = headerValue;
return true;
}
}
}
if(headerLine == "") {
DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] code: '%s'\n", String(_returnCode).c_str());
if(_size) {
DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] size: '%s'\n", String(_size).c_str());
}
return _returnCode;
}
} else {
delay(0);
}
}
}

View File

@ -43,20 +43,38 @@ class httpClient {
bool connected(void); bool connected(void);
bool GET(); /// request handling
bool POST(uint8_t * payload, size_t size); int GET();
bool POST(String payload); int POST(uint8_t * payload, size_t size);
int POST(String payload);
void addHeader(const String& name, const String& value, bool first = false); void addHeader(const String& name, const String& value, bool first = false);
/// Response handling
void collectHeaders(const char* headerKeys[], const size_t headerKeysCount);
String header(const char* name); // get request header value by name
String header(int i); // get request header value by number
String headerName(int i); // get request header name by number
int headers(); // get header count
bool hasHeader(const char* name); // check if header exists
size_t getSize(void);
WiFiClient & getStream(void); WiFiClient & getStream(void);
protected: protected:
struct RequestArgument {
String key;
String value;
};
WiFiClient * _tcp; WiFiClient * _tcp;
WiFiClientSecure * _tcps; WiFiClientSecure * _tcps;
/// request handling
String _host; String _host;
uint16_t _port; uint16_t _port;
@ -66,10 +84,17 @@ class httpClient {
String _Headers; String _Headers;
/// Response handling
RequestArgument* _currentHeaders;
size_t _headerKeysCount;
int _returnCode;
size_t _size;
bool connect(void); bool connect(void);
bool sendHeader(const char * type); bool sendHeader(const char * type);
int handleHeaderResponse();
}; };