Corrected the isReplyAvailable methode
This commit is contained in:
parent
2f430b305c
commit
f76639745f
@ -7,20 +7,8 @@
|
||||
* End of HttpClientHelper
|
||||
*/
|
||||
|
||||
HttpClient::HttpClient() : WiFiClient(), _connectionStatus(NO_ATTEMPT), _resource(NULL), _address(NULL), _port(0), _keepAlive(false), _maxRetries(-1), _retries(0), _httpCode(HTTP_CODE::UNDEFINED_CODE), _bodyReadyToRead(false)
|
||||
HttpClient::HttpClient(const char *address, uint16_t port) : WiFiClient(), _connectionStatus(NO_ATTEMPT), _resource(NULL), _pAddress(address), _port(0), _keepAlive(false), _maxRetries(-1), _retries(0), _isIp(false), _httpCode(HTTP_CODE::UNDEFINED_CODE), _httpCodeParsed(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HttpClient::HttpClient(const char *address, uint16_t port) : HttpClient()
|
||||
{
|
||||
|
||||
if(address != NULL)
|
||||
{
|
||||
_address = (char *)malloc(strlen(address) * sizeof(char) + 1);
|
||||
strcpy(_address, address);
|
||||
}
|
||||
|
||||
_port = port;
|
||||
|
||||
connectByHostOrIp();
|
||||
@ -45,34 +33,27 @@ HttpClient::HttpClient(const HttpClient &object)
|
||||
else
|
||||
_resource = NULL;
|
||||
|
||||
if(object._address != NULL)
|
||||
{
|
||||
_address = (char *)malloc(strlen(object._address) * sizeof(char) + 1);
|
||||
strcpy(_address, object._address);
|
||||
}
|
||||
else
|
||||
_address = NULL;
|
||||
|
||||
_pAddress = object._pAddress;
|
||||
_connectionStatus = object._connectionStatus;
|
||||
_keepAlive = object._keepAlive;
|
||||
_maxRetries = object._maxRetries;
|
||||
_retries = object._retries;
|
||||
_port = object._port;
|
||||
_httpCode = object._httpCode;
|
||||
_bodyReadyToRead = object._bodyReadyToRead;
|
||||
_httpCodeParsed = object._httpCodeParsed;
|
||||
}
|
||||
|
||||
HttpClient::~HttpClient()
|
||||
{
|
||||
if(_resource != NULL)free(_resource);
|
||||
if(_address != NULL)free(_address);
|
||||
}
|
||||
|
||||
boolean HttpClient::connectByHostOrIp()
|
||||
{
|
||||
IPAddress ipAddress;
|
||||
if(ipAddress.fromString(_address))
|
||||
if(ipAddress.fromString(_pAddress))
|
||||
{
|
||||
_isIp = true;
|
||||
_connectionStatus = connect(ipAddress, _port) == 1 ? SUCCESSFUL : FAILED;
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("Correct ip address. Connection status : %d\n", _connectionStatus);
|
||||
@ -80,7 +61,8 @@ boolean HttpClient::connectByHostOrIp()
|
||||
}
|
||||
else
|
||||
{
|
||||
_connectionStatus = connect(_address, _port) == 1 ? SUCCESSFUL : FAILED;
|
||||
_isIp = false;
|
||||
_connectionStatus = connect(_pAddress, _port) == 1 ? SUCCESSFUL : FAILED;
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("Probably a hostname. Connection status : %d\n", _connectionStatus);
|
||||
#endif
|
||||
@ -108,7 +90,7 @@ boolean HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary<Dictionar
|
||||
{
|
||||
//We reset this two flags
|
||||
_httpCode = HTTP_CODE::UNDEFINED_CODE;
|
||||
_bodyReadyToRead = false;
|
||||
_httpCodeParsed = false;
|
||||
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
if(_keepAlive)
|
||||
@ -127,9 +109,9 @@ boolean HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary<Dictionar
|
||||
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
if(_keepAlive)
|
||||
Serial.printf("Link broken, we try to reconnect : addr : %s port %u\nretries : %u\n", _address, _port, _retries);
|
||||
Serial.printf("Link broken, we try to reconnect : addr : %s port %u\nretries : %u\n", _pAddress, _port, _retries);
|
||||
else
|
||||
Serial.printf("We start a new connection : %s port %u\nretries : %u\n", _address, _port, _retries);
|
||||
Serial.printf("We start a new connection : %s port %u\nretries : %u\n", _pAddress, _port, _retries);
|
||||
#endif
|
||||
|
||||
connectByHostOrIp();
|
||||
@ -180,71 +162,125 @@ boolean HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary<Dictionar
|
||||
return true;
|
||||
}
|
||||
|
||||
HttpClient::HTTP_CODE HttpClient::isReplyAvailable()
|
||||
HttpClient::HTTP_CODE HttpClient::isReplyAvailable(uint16_t timeout)
|
||||
{
|
||||
uint32_t bytesAvailable(available());
|
||||
uint8_t readBuffer[100];
|
||||
uint8_t safeSize;
|
||||
uint32_t ts(millis());
|
||||
char buffer[100];
|
||||
|
||||
if(bytesAvailable && !_bodyReadyToRead)
|
||||
if(!_httpCodeParsed)_httpCodeParsed = true;
|
||||
else
|
||||
{
|
||||
safeSize = bytesAvailable > 99 ? 99 : bytesAvailable;
|
||||
peekBytes(readBuffer, safeSize);
|
||||
readBuffer[safeSize] = '\0';
|
||||
return _httpCode;
|
||||
}
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.println("Before timeout");
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("Data chunk from server size -> %u - %u : %s\n", safeSize, bytesAvailable, readBuffer);
|
||||
#endif
|
||||
|
||||
//We try to extract the http return code:
|
||||
if(_httpCode == HTTP_CODE::UNDEFINED_CODE)
|
||||
//This is the loop where we parse the data
|
||||
while(available() || millis() - ts < timeout)
|
||||
{
|
||||
if(available())
|
||||
{
|
||||
char *code = strchr((char *)readBuffer, ' '), *endP;
|
||||
|
||||
if(code != NULL)
|
||||
//If we do not have the HTTP response code yet, we parse it
|
||||
if(_httpCode == HTTP_CODE::UNDEFINED_CODE)
|
||||
{
|
||||
endP = strchr(code + 1, ' ');
|
||||
if(endP != NULL)
|
||||
uint8_t bytesRed = buffer[peekBytes((uint8_t*)buffer,99)] = '\0';
|
||||
//We look for the end of the first line ie : HTTP/1.1 200 OK\r\n
|
||||
char *pNewLine = strstr(buffer, "\r\n");
|
||||
//If we found the new line, we can retrieve the code
|
||||
if(pNewLine)
|
||||
{
|
||||
*endP = '\0';
|
||||
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("Http code : %s\n", code + 1);
|
||||
Serial.println("New line found");
|
||||
#endif
|
||||
//We extract the code
|
||||
char *code = strchr((char *)buffer, ' '), *endP;
|
||||
if(code)
|
||||
{
|
||||
endP = strchr(code + 1, ' ');
|
||||
if(endP != NULL)
|
||||
{
|
||||
*endP = '\0';
|
||||
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("Http code : %s\n", code + 1);
|
||||
#endif
|
||||
|
||||
|
||||
_httpCode = numberToHTTP_CODE(strtoul(code+1, NULL, 10));
|
||||
read(readBuffer, safeSize - 4); //To remove the peek bytes
|
||||
_httpCode = numberToHTTP_CODE(strtoul(code+1, NULL, 10));
|
||||
//We can now discard the first line
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("First line length : %u\n",(pNewLine - buffer) + 2);
|
||||
#endif
|
||||
read((uint8_t *)buffer, (pNewLine - buffer) + 2);
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
buffer[peekBytes((uint8_t*)buffer,99)] = '\0';
|
||||
Serial.printf("Next chunk is : %s\n",buffer);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.println("Code delimiter NOT found, leaving");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(millis() - ts >= timeout)//Time out is over, received data is probably junk.
|
||||
{
|
||||
//we leave the loop;
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.println("New line NOT found, leaving");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!_bodyReadyToRead)
|
||||
{
|
||||
char *endP = strstr((char *)readBuffer, "\r\n\r\n");
|
||||
|
||||
if(endP != NULL)
|
||||
else//We found the HTTP code, now we discard all the header data
|
||||
{
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.printf("Body found, bytes to discard : %u\n", (uint8_t *)endP - readBuffer + 4);
|
||||
#endif
|
||||
read(readBuffer, (uint8_t *)endP - readBuffer + 4);
|
||||
_bodyReadyToRead = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
read(readBuffer, safeSize - 3);
|
||||
char *bodyDelimiter(NULL);
|
||||
char *newLineDelimiter;
|
||||
do
|
||||
{
|
||||
buffer[peekBytes((uint8_t*)buffer,99)] = '\0';
|
||||
bodyDelimiter = strstr(buffer, "\r\n\r\n");
|
||||
newLineDelimiter = strstr(buffer, "\r\n");
|
||||
if(!bodyDelimiter)
|
||||
{
|
||||
if(newLineDelimiter)
|
||||
{
|
||||
read((uint8_t *)buffer, (newLineDelimiter - buffer) + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
read((uint8_t *)buffer, strlen(buffer));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.println("We found the body delimiter");
|
||||
#endif
|
||||
read((uint8_t *)buffer, (bodyDelimiter - buffer) + 4);
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
buffer[peekBytes((uint8_t*)buffer,99)] = '\0';
|
||||
Serial.printf("Body chunk is : %s\n",buffer);
|
||||
#endif
|
||||
}
|
||||
}while(!bodyDelimiter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(_httpCode != HTTP_CODE::UNDEFINED_CODE && _bodyReadyToRead)
|
||||
return _httpCode;
|
||||
#ifdef DEBUG_HTTP_CLIENT
|
||||
Serial.println("\nAfter timeout or all data is received");
|
||||
#endif
|
||||
|
||||
return HTTP_CODE::UNDEFINED_CODE;
|
||||
return _httpCode;
|
||||
}
|
||||
|
||||
uint16_t HttpClient::readHttpReply(uint8_t *buffer, uint32_t size)
|
||||
uint16_t HttpClient::readHttpBody(uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
uint32_t bytesAvailable(available());
|
||||
uint8_t safeSize(0);
|
||||
@ -310,7 +346,12 @@ void HttpClient::keepAlive(boolean enabled)
|
||||
void HttpClient::sendHeader(HttpMIMEType contentType, uint64_t contentLength, HttpVersion httpVersion)
|
||||
{
|
||||
char mime[255] = "", httpVer[15] = "";
|
||||
printf(" %s\r\nHost: %u.%u.%u.%u:%u\r\nConnection: %s\r\n", httpVersionToString(httpVersion, httpVer), remoteIP()[0], remoteIP()[1], remoteIP()[2], remoteIP()[3], remotePort(), _keepAlive ? "keep-alive" : "close");
|
||||
//Host could be an IP address or a host name
|
||||
if(_isIp)
|
||||
printf(" %s\r\nHost: %u.%u.%u.%u:%u\r\nConnection: %s\r\n", httpVersionToString(httpVersion, httpVer), remoteIP()[0], remoteIP()[1], remoteIP()[2], remoteIP()[3], remotePort(), _keepAlive ? "keep-alive" : "close");
|
||||
else
|
||||
printf(" %s\r\nHost: %s\r\nConnection: %s\r\n", httpVersionToString(httpVersion, httpVer), _pAddress, _keepAlive ? "keep-alive" : "close");
|
||||
|
||||
if(contentLength > 0)
|
||||
{
|
||||
printf("Content-Length: %u\r\n", contentLength);
|
||||
|
@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Anatole SCHRAMM-HENRY
|
||||
* Updated on 12/07/2020
|
||||
*/
|
||||
#ifndef HTTPCLIENT_H
|
||||
#define HTTPCLIENT_H
|
||||
|
||||
@ -15,7 +19,6 @@ class HttpClient : public WiFiClient, public HttpConstants
|
||||
public:
|
||||
enum ConnectionStatus { NO_ATTEMPT = 0, SUCCESSFUL, FAILED };
|
||||
|
||||
HttpClient();
|
||||
HttpClient(const char *address, uint16_t port = 80);
|
||||
HttpClient(const char *address, const char *resource, uint16_t port = 80);
|
||||
|
||||
@ -26,10 +29,10 @@ class HttpClient : public WiFiClient, public HttpConstants
|
||||
boolean sendHttpQuery(HttpRequestMethod method = HttpRequestMethod::GET, Dictionary<DictionaryHelper::StringEntity> *getData = NULL, Dictionary<DictionaryHelper::StringEntity> *postData = NULL);
|
||||
void keepAlive(boolean enabled);
|
||||
void setMaxRetries(int16_t retries);
|
||||
//100 ms is the default timeout
|
||||
HTTP_CODE isReplyAvailable(uint16_t timeout = 100);
|
||||
|
||||
HTTP_CODE isReplyAvailable();
|
||||
|
||||
uint16_t readHttpReply(uint8_t *buffer, uint32_t size);
|
||||
uint16_t readHttpBody(uint8_t *buffer, uint32_t size);
|
||||
protected:
|
||||
private:
|
||||
boolean connectByHostOrIp();
|
||||
@ -40,13 +43,14 @@ class HttpClient : public WiFiClient, public HttpConstants
|
||||
|
||||
ConnectionStatus _connectionStatus;
|
||||
char *_resource;
|
||||
char *_address;
|
||||
const char *_pAddress;
|
||||
uint16_t _port;
|
||||
boolean _keepAlive;
|
||||
int16_t _maxRetries;
|
||||
uint16_t _retries;
|
||||
boolean _isIp;
|
||||
HTTP_CODE _httpCode;
|
||||
boolean _bodyReadyToRead;
|
||||
boolean _httpCodeParsed;
|
||||
};
|
||||
|
||||
#endif //HTTPCLIENT_H
|
||||
|
Loading…
Reference in New Issue
Block a user