233 lines
11 KiB
C++
233 lines
11 KiB
C++
#ifndef asyncHTTPrequest_h
|
|
#define asyncHTTPrequest_h "1.1.15"
|
|
|
|
/***********************************************************************************
|
|
Copyright (C) <2018> <Bob Lemaire, IoTaWatt, Inc.>
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
***********************************************************************************/
|
|
|
|
#ifndef DEBUG_IOTA_PORT
|
|
#define DEBUG_IOTA_PORT Serial
|
|
#endif
|
|
|
|
#ifdef DEBUG_IOTA_HTTP
|
|
#define DEBUG_IOTA_HTTP_SET true
|
|
#else
|
|
#define DEBUG_IOTA_HTTP_SET false
|
|
#endif
|
|
|
|
#include <Arduino.h>
|
|
#ifdef ESP32
|
|
//#include <ESPAsyncTCP.h>
|
|
#include "../../AsyncTCP/src/AsyncTCP.h"
|
|
#include "freertos/queue.h"
|
|
#define _seize xSemaphoreTakeRecursive(threadLock,portMAX_DELAY)
|
|
#define _release xSemaphoreGiveRecursive(threadLock)
|
|
#endif
|
|
|
|
#include <pgmspace.h>
|
|
#include "xbuf.h"
|
|
|
|
#define DEBUG_HTTP(format,...) if(_debug){\
|
|
DEBUG_IOTA_PORT.printf("Debug(%3ld): ", millis()-_requestStartTime);\
|
|
DEBUG_IOTA_PORT.printf_P(PSTR(format),##__VA_ARGS__);}
|
|
|
|
#define DEFAULT_RX_TIMEOUT 3 // Seconds for timeout
|
|
|
|
#define HTTPCODE_CONNECTION_REFUSED (-1)
|
|
#define HTTPCODE_SEND_HEADER_FAILED (-2)
|
|
#define HTTPCODE_SEND_PAYLOAD_FAILED (-3)
|
|
#define HTTPCODE_NOT_CONNECTED (-4)
|
|
#define HTTPCODE_CONNECTION_LOST (-5)
|
|
#define HTTPCODE_NO_STREAM (-6)
|
|
#define HTTPCODE_NO_HTTP_SERVER (-7)
|
|
#define HTTPCODE_TOO_LESS_RAM (-8)
|
|
#define HTTPCODE_ENCODING (-9)
|
|
#define HTTPCODE_STREAM_WRITE (-10)
|
|
#define HTTPCODE_TIMEOUT (-11)
|
|
|
|
class asyncHTTPrequest {
|
|
|
|
struct header {
|
|
header* next;
|
|
char* name;
|
|
char* value;
|
|
header():
|
|
next(nullptr),
|
|
name(nullptr),
|
|
value(nullptr)
|
|
{};
|
|
~header(){
|
|
delete[] name;
|
|
delete[] value;
|
|
delete next;
|
|
}
|
|
};
|
|
|
|
struct URL {
|
|
char* scheme;
|
|
char* user;
|
|
char* pwd;
|
|
char* host;
|
|
int port;
|
|
char* path;
|
|
char* query;
|
|
char* fragment;
|
|
URL():
|
|
scheme(nullptr),
|
|
user(nullptr),
|
|
pwd(nullptr),
|
|
host(nullptr),
|
|
port(80),
|
|
path(nullptr),
|
|
query(nullptr),
|
|
fragment(nullptr)
|
|
{};
|
|
~URL(){
|
|
delete[] scheme;
|
|
delete[] user;
|
|
delete[] pwd;
|
|
delete[] host;
|
|
delete[] path;
|
|
delete[] query;
|
|
delete[] fragment;
|
|
}
|
|
};
|
|
|
|
typedef std::function<void(void*, asyncHTTPrequest*, int readyState)> readyStateChangeCB;
|
|
typedef std::function<void(void*, asyncHTTPrequest*, size_t available)> onDataCB;
|
|
typedef std::function<void(void*, asyncHTTPrequest*)> onBuildHeadersCB;
|
|
|
|
public:
|
|
asyncHTTPrequest();
|
|
~asyncHTTPrequest();
|
|
|
|
|
|
//External functions in typical order of use:
|
|
//__________________________________________________________________________________________________________*/
|
|
void setDebug(bool); // Turn debug message on/off
|
|
bool debug(); // is debug on or off?
|
|
|
|
bool open(const char* /*GET/POST*/, const char* URL); // Initiate a request
|
|
void onReadyStateChange(readyStateChangeCB, void* arg = 0); // Optional event handler for ready state change
|
|
// or you can simply poll readyState()
|
|
void setTimeout(int); // overide default timeout (seconds)
|
|
|
|
void setReqHeader(const char* name, const char* value); // add a request header
|
|
void setReqHeader(const char* name, const __FlashStringHelper* value);
|
|
void setReqHeader(const __FlashStringHelper *name, const char* value);
|
|
void setReqHeader(const __FlashStringHelper *name, const __FlashStringHelper* value);
|
|
|
|
void setReqHeader(const char* name, int32_t value); // overload to use integer value
|
|
void setReqHeader(const __FlashStringHelper *name, int32_t value);
|
|
|
|
bool send(); // Send the request (GET)
|
|
bool send(String body); // Send the request (POST)
|
|
bool send(const char* body); // Send the request (POST)
|
|
bool send(const uint8_t* buffer, size_t len); // Send the request (POST) (binary data?)
|
|
bool send(xbuf* body, size_t len); // Send the request (POST) data in an xbuf
|
|
void abort(); // Abort the current operation
|
|
void close(); // Close the connection
|
|
|
|
int readyState() const; // Return the ready state
|
|
|
|
int respHeaderCount(); // Retrieve count of response headers
|
|
char* respHeaderName(int index); // Return header name by index
|
|
char* respHeaderValue(int index); // Return header value by index
|
|
char* respHeaderValue(const char* name); // Return header value by name
|
|
char* respHeaderValue(const __FlashStringHelper *name);
|
|
bool respHeaderExists(const char* name); // Does header exist by name?
|
|
bool respHeaderExists(const __FlashStringHelper *name);
|
|
String headers(); // Return all headers as String
|
|
|
|
void onData(onDataCB, void* arg = 0); // Notify when min data is available
|
|
size_t available(); // response available
|
|
size_t responseLength(); // indicated response length or sum of chunks to date
|
|
int responseHTTPcode(); // HTTP response code or (negative) error code
|
|
String responseText(); // response (whole* or partial* as string)
|
|
size_t responseRead(uint8_t* buffer, size_t len); // Read response into buffer
|
|
uint32_t elapsedTime(); // Elapsed time of in progress transaction or last completed (ms)
|
|
String version(); // Version of asyncHTTPrequest
|
|
|
|
void onBuildHeaders(onBuildHeadersCB, void* arg = 0); // notify for additional headers if required
|
|
//___________________________________________________________________________________________________________________________________
|
|
|
|
private:
|
|
|
|
enum {HTTPmethodGET, HTTPmethodPOST} _HTTPmethod;
|
|
|
|
enum readyStates {
|
|
readyStateUnsent = 0, // Client created, open not yet called
|
|
readyStateOpened = 1, // open() has been called, connected
|
|
readyStateHdrsRecvd = 2, // send() called, response headers available
|
|
readyStateLoading = 3, // receiving, partial data available
|
|
readyStateDone = 4} _readyState; // Request complete, all data available.
|
|
|
|
int16_t _HTTPcode; // HTTP response code or (negative) exception code
|
|
bool _chunked; // Processing chunked response
|
|
bool _debug; // Debug state
|
|
uint32_t _timeout; // Default or user overide RxTimeout in seconds
|
|
uint32_t _lastActivity; // Time of last activity
|
|
uint32_t _requestStartTime; // Time last open() issued
|
|
uint32_t _requestEndTime; // Time of last disconnect
|
|
URL* _URL; // -> URL data structure
|
|
char* _connectedHost; // Host when connected
|
|
int _connectedPort; // Port when connected
|
|
AsyncClient* _client; // ESPAsyncTCP AsyncClient instance
|
|
size_t _contentLength; // content-length header value or sum of chunk headers
|
|
size_t _contentRead; // number of bytes retrieved by user since last open()
|
|
readyStateChangeCB _readyStateChangeCB; // optional callback for readyState change
|
|
void* _readyStateChangeCBarg; // associated user argument
|
|
onDataCB _onDataCB; // optional callback when data received
|
|
void* _onDataCBarg; // associated user argument
|
|
onBuildHeadersCB _onBuildHeadersCB; // optional callback to add extra HTTP headers
|
|
void* _onBuildHeadersCBarg; // associated user argument
|
|
|
|
#ifdef ESP32
|
|
SemaphoreHandle_t threadLock;
|
|
#endif
|
|
|
|
// request and response String buffers and header list (same queue for request and response).
|
|
|
|
xbuf* _request; // Tx data buffer
|
|
xbuf* _response; // Rx data buffer for headers
|
|
xbuf* _chunks; // First stage for chunked response
|
|
header* _headers; // request or (readyState > readyStateHdrsRcvd) response headers
|
|
|
|
// Protected functions
|
|
|
|
header* _addHeader(const char*, const char*);
|
|
header* _getHeader(const char*);
|
|
header* _getHeader(int);
|
|
bool _buildRequest();
|
|
bool _parseURL(const char*);
|
|
bool _parseURL(String);
|
|
void _processChunks();
|
|
bool _connect();
|
|
size_t _send();
|
|
void _setReadyState(readyStates);
|
|
char* _charstar(const __FlashStringHelper *str);
|
|
|
|
// callbacks
|
|
|
|
void _onConnect(AsyncClient*);
|
|
void _onDisconnect(AsyncClient*);
|
|
void _onData(void*, size_t);
|
|
void _onError(AsyncClient*, int8_t);
|
|
void _onPoll(AsyncClient*);
|
|
bool _collectHeaders();
|
|
};
|
|
#endif |