2 #include "AudioConfig.h"
5 #include "AudioHttp/HttpChunkReader.h"
6 #include "AudioHttp/HttpHeader.h"
7 #include "AudioHttp/HttpTypes.h"
8 #include "AudioHttp/Url.h"
9 #include "AudioTools/AudioLogger.h"
11 #define CHUNK_SIZE 1024
36 void setClient(
Client &client) {
37 this->client_ptr = &client;
38 this->client_ptr->setTimeout(clientTimeout);
43 void setHost(
const char *host) {
44 LOGI(
"setHost %s", host);
45 this->host_name = host;
48 operator bool() {
return client_ptr !=
nullptr ? (bool)*client_ptr :
false; }
50 virtual bool connected() {
51 return client_ptr ==
nullptr ? false : client_ptr->connected();
54 virtual int available() {
55 if (reply_header.isChunked()) {
56 return chunk_reader.available();
58 return client_ptr !=
nullptr ? client_ptr->available() : 0;
69 virtual int post(
Url &url,
const char *mime,
const char *data,
int len = -1) {
70 LOGI(
"post %s", url.url());
71 return process(POST, url, mime, data, len);
75 virtual int post(
Url &url,
const char *mime,
Stream &data,
int len = -1) {
76 LOGI(
"post %s", url.url());
77 return process(POST, url, mime, data, len);
81 virtual int put(
Url &url,
const char *mime,
const char *data,
int len = -1) {
82 LOGI(
"put %s", url.url());
83 return process(PUT, url, mime, data, len);
87 virtual int put(
Url &url,
const char *mime,
Stream &data,
int len = -1) {
88 LOGI(
"put %s", url.url());
89 return process(PUT, url, mime, data, len);
93 virtual int del(
Url &url,
const char *mime =
nullptr,
94 const char *data =
nullptr,
int len = -1) {
95 LOGI(
"del %s", url.url());
96 return process(DELETE, url, mime, data, len);
100 virtual int get(
Url &url,
const char *acceptMime =
nullptr,
101 const char *data =
nullptr,
int len = -1) {
102 LOGI(
"get %s", url.url());
103 this->accept = acceptMime;
104 return process(GET, url,
nullptr, data, len);
108 virtual int head(
Url &url,
const char *acceptMime =
nullptr,
109 const char *data =
nullptr,
int len = -1) {
110 LOGI(
"head %s", url.url());
111 this->accept = acceptMime;
112 return process(HEAD, url,
nullptr, data, len);
116 virtual int read(uint8_t *str,
int len) {
118 if (reply_header.isChunked()) {
119 return chunk_reader.read(*client_ptr, str, len);
121 return client_ptr->read(str, len);
125 size_t readBytesUntil(
char terminator,
char *buffer,
size_t length) {
126 return client_ptr->readBytesUntil(terminator, buffer, length);
131 virtual int readln(uint8_t *str,
int len,
bool incl_nl =
true) {
132 if (reply_header.isChunked()) {
133 return chunk_reader.readln(*client_ptr, str, len);
135 return chunk_reader.readlnInternal(*client_ptr, str, len, incl_nl);
140 virtual HttpReplyHeader &reply() {
return reply_header; }
146 virtual void setAgent(
const char *agent) { this->agent = agent; }
148 virtual void setConnection(
const char *connection) {
149 this->connection = connection;
152 virtual void setAcceptsEncoding(
const char *enc) {
153 this->accept_encoding = enc;
156 virtual void setAcceptMime(
const char *mime) { this->accept = mime; }
158 size_t contentLength() {
159 const char *len_str = reply().get(CONTENT_LENGTH);
161 if (len_str !=
nullptr) {
164 LOGI(
"no CONTENT_LENGTH found in reply");
175 request_header.put(
header, value);
178 Client &client() {
return *client_ptr; }
181 virtual int process(MethodID action, Url &url,
const char *mime,
182 const char *data,
int lenData = -1) {
184 if (data !=
nullptr && len <= 0) {
189 if (len > 0 && data !=
nullptr) {
190 LOGI(
"Writing data: %d bytes", len);
191 client_ptr->write((
const uint8_t *)data, len);
198 virtual int process(MethodID action, Url &url,
const char *mime,
199 Stream &stream,
int len = -1) {
212 if (client_ptr ==
nullptr) {
213 LOGE(
"The client has not been defined");
216 if (http_connect_callback) {
217 http_connect_callback(*
this, url, request_header);
219 if (!this->connected()) {
220 LOGI(
"process connecting to host %s port %d", url.host(), url.port());
221 int is_connected = connect(url.host(), url.port(), clientTimeout);
223 LOGE(
"Connect failed");
227 LOGI(
"process is already connected");
230 #if defined(ESP32) && defined(ARDUINO)
231 LOGI(
"Free heap: %u", (
unsigned)ESP.getFreeHeap());
234 reply_header.setProcessed();
236 host_name = url.host();
237 request_header.setValues(action, url.path());
239 request_header.put(CONTENT_LENGTH, lenData);
241 request_header.put(HOST_C, host_name);
242 request_header.put(CONNECTION, connection);
243 request_header.put(USER_AGENT, agent);
244 request_header.put(ACCEPT_ENCODING, accept_encoding);
245 request_header.put(ACCEPT, accept);
246 request_header.put(CONTENT_TYPE, mime);
247 request_header.
write(*client_ptr);
254 uint8_t buffer[CHUNK_SIZE];
256 int total_written = 0;
257 while (*client_ptr && stream.available() > 0) {
258 int result_len = stream.readBytes(buffer, CHUNK_SIZE);
260 int written =
write(buffer, result_len);
261 total_written += written;
262 LOGI(
"--> Bytes read %d vs written %d", result_len, written);
266 LOGI(
"Total bytes read %d vs written %d", total, total_written);
271 virtual size_t write(uint8_t *data,
size_t len) {
274 client_ptr->println(len);
276 result = client_ptr->write(data, len);
278 client_ptr->println();
280 result = client_ptr->write(data, len);
291 LOGI(
"Request written ... waiting for reply")
294 reply_header.
read(*client_ptr);
297 if (reply_header.isChunked()) {
298 chunk_reader.open(*client_ptr);
303 return reply_header.statusCode();
309 http_connect_callback = callback;
313 void setTimeout(
int timeoutMs) { clientTimeout = timeoutMs; }
319 Client *client_ptr =
nullptr;
324 const char *agent =
nullptr;
325 const char *host_name =
nullptr;
326 const char *connection = CON_KEEP_ALIVE;
327 const char *accept = ACCEPT_ALL;
328 const char *accept_encoding = IDENTITY;
329 bool is_ready =
false;
330 int32_t clientTimeout = URL_CLIENT_TIMEOUT;
335 virtual int connect(
const char *ip, uint16_t port, int32_t timeout) {
336 client_ptr->setTimeout(timeout / 1000);
339 int is_connected = this->client_ptr->connect(ip, port);
340 LOGI(
"is connected %s with timeout %d", is_connected ?
"true" :
"false", (
int)timeout);
void stop()
Public generic methods.
Definition: AudioRuntime.h:12