64 protocol_str =
"HTTP/1.1";
79 for (
auto& ptr : lines){
86 HttpHeader& put(
const char* key,
const char* value) {
87 if (value !=
nullptr && strlen(value) > 0) {
88 LOGD(
"HttpHeader::put %s %s", key, value);
91 if (create_new_lines){
92 LOGE(
"HttpHeader::put - did not add HttpHeaderLine for %s", key);
98 LOGD(
"HttpHeader::put -> '%s' : '%s'", key, value);
104 if (StrView(key).equalsIgnoreCase(TRANSFER_ENCODING) && StrView(value) == CHUNKED) {
105 LOGI(
"- is_chunked!!!");
106 this->is_chunked =
true;
109 if (StrView(key).equalsIgnoreCase(CONTENT_TYPE)) {
110 LOGI(
"%s: %s", CONTENT_TYPE, value);
113 LOGD(
"HttpHeader::put - value ignored because it is null for %s", key);
120 LOGD(
"HttpHeader::put %s %d", key, value);
124 LOGW(
"value is > 1000");
130 LOGI(
"%s %s", key, hl->value.
c_str());
136 LOGD(
"HttpHeader::put -> %s", (
const char*)line);
139 char* key = (
char*)line;
143 const char* value = line + pos + 1;
144 if (value[0] ==
' ') {
145 value = line + pos + 2;
147 return put((
const char*)key, value);
151 const char* get(
const char* key) {
152 for (
auto& line_ptr : lines) {
155 line_ptr->key = trimmed.c_str();
157 if (StrView(line_ptr->key.c_str()).equalsIgnoreCase(key)) {
158 const char* result = line_ptr->value.c_str();
159 return line_ptr->active ? result :
nullptr;
166 int readLine(Client& in,
char* str,
int len) {
167 int result = reader.readlnInternal(in, (uint8_t*)str, len,
false);
168 LOGD(
"HttpHeader::readLine -> %s", str);
173 void writeHeaderLine(Client& out, HttpHeaderLine& header) {
174 LOGD(
"HttpHeader::writeHeaderLine: %s", header.key.c_str());
175 if (!header.active) {
176 LOGD(
"HttpHeader::writeHeaderLine - not active");
179 if (header.value.c_str() ==
nullptr) {
180 LOGD(
"HttpHeader::writeHeaderLine - ignored because value is null");
184 char* msg = tempBuffer();
185 StrView msg_str(msg, HTTP_MAX_LEN);
186 msg_str = header.key.c_str();
188 msg_str += header.value.c_str();
190 out.print(msg_str.c_str());
194 int len = strlen(msg);
196 LOGI(
" -> %s ", msg);
202 const char* urlPath() {
return url_path.
c_str(); }
204 MethodID method() {
return method_id; }
206 int statusCode() {
return status_code; }
208 const char* statusMessage() {
return status_msg.
c_str(); }
217 LOGD(
"HttpHeader::read");
221 char* line = tempBuffer();
222 if (in.connected()) {
223 if (in.available() == 0) {
225 uint32_t timeout =
millis() + timeout_ms;
226 while (in.available() == 0) {
230 LOGI(
"Waiting for data...");
234 LOGE(
"Request timed out after %d ms", (
int)timeout_ms);
239 LOGI(
"Data available: %d", in.available());
242 readLine(in, line, HTTP_MAX_LEN);
245 int len = readLine(in, line, HTTP_MAX_LEN);
246 if (len == 0 && in.available() == 0)
break;
262 LOGI(
"HttpHeader::write");
264 for (
auto& line_ptr : lines) {
265 writeHeaderLine(out, *line_ptr);
273 void setProcessed() {
274 for (
auto& line :lines) {
275 line->active =
false;
281 create_new_lines = is_auto_line;
291 void end() { temp_buffer.resize(0); }
300 void setProtocol(
const char* protocal) { protocol_str = protocal; }
304 temp_buffer.resize(bufferSize);
313 int status_code = UNDEFINED;
314 bool is_written =
false;
315 bool is_chunked =
false;
316 bool create_new_lines =
true;
321 Str protocol_str{10};
324 List<HttpHeaderLine*> lines;
325 HttpLineReader reader;
326 const char* CRLF =
"\r\n";
327 int timeout_ms = URL_CLIENT_TIMEOUT;
328 Vector<char> temp_buffer{HTTP_MAX_LEN};
332 return temp_buffer.data();
336 void crlf(Client& out) {
338 LOGI(
" -> %s ",
"<CR LF>");
342 HttpHeaderLine* headerLine(
const char* key) {
343 if (key !=
nullptr) {
344 for (
auto& line_ptr : lines) {
345 if (line_ptr->key.c_str() !=
nullptr) {
346 if (line_ptr->key.equalsIgnoreCase(key)) {
347 line_ptr->active =
true;
352 if (create_new_lines || StrView(key).equalsIgnoreCase(CONTENT_LENGTH) ||
353 StrView(key).equalsIgnoreCase(CONTENT_TYPE)) {
354 HttpHeaderLine *new_line =
new HttpHeaderLine(key);
355 lines.push_back(new_line);
359 LOGI(
"HttpHeader::headerLine %s",
"The key must not be null");
364 MethodID getMethod(
const char* line) {
366 for (
int j = 0; methods[j] !=
nullptr; j++) {
367 const char* action = methods[j];
368 int len = strlen(action);
369 if (strncmp(action, line, len) == 0) {
376 virtual void write1stLine(Client& out) = 0;
377 virtual void parse1stLine(
const char* line) = 0;
388 HttpHeader& setValues(MethodID
id,
const char* urlPath,
390 this->method_id = id;
391 this->url_path = urlPath;
393 LOGD(
"HttpRequestHeader::setValues - path: %s", this->url_path.
c_str());
401 void write1stLine(
Client& out) {
402 LOGD(
"HttpRequestHeader::write1stLine");
403 char* msg = tempBuffer();
404 StrView msg_str(msg, HTTP_MAX_LEN);
406 const char* method_str = methods[this->method_id];
407 msg_str = method_str;
409 msg_str += this->url_path.
c_str();
411 msg_str += this->protocol_str.
c_str();
415 int len = strlen(msg);
422 void parse1stLine(
const char* line) {
423 LOGD(
"HttpRequestHeader::parse1stLine %s", line);
425 int space1 = line_str.
indexOf(
" ");
426 int space2 = line_str.
indexOf(
" ", space1 + 1);
428 this->method_id = getMethod(line);
430 this->url_path.
substring(line_str, space1 + 1, space2);
431 this->url_path.
trim();
433 LOGD(
"->method %s", methods[this->method_id]);
434 LOGD(
"->protocol %s", protocol_str.
c_str());
435 LOGD(
"->url_path %s", url_path.
c_str());
447 void setValues(
int statusCode,
const char* msg =
"",
449 LOGI(
"HttpReplyHeader::setValues");
451 status_code = statusCode;
458 void readExt(
Client& in) {
459 LOGI(
"HttpReplyHeader::readExt");
460 char* line = tempBuffer();
461 readLine(in, line, HTTP_MAX_LEN);
462 while (strlen(line) != 0) {
464 readLine(in, line, HTTP_MAX_LEN);
469 void write1stLine(
Client& out) {
470 LOGI(
"HttpReplyHeader::write1stLine");
471 char* msg = tempBuffer();
472 StrView msg_str(msg, HTTP_MAX_LEN);
473 msg_str = this->protocol_str.
c_str();
475 msg_str += this->status_code;
477 msg_str += this->status_msg.
c_str();
486 void parse1stLine(
const char* line) {
487 LOGD(
"HttpReplyHeader::parse1stLine: %s", line);
489 int space1 = line_str.
indexOf(
' ', 0);
490 int space2 = line_str.
indexOf(
' ', space1 + 1);
493 protocol_str.
substring(line_str, 0, space1);
498 status.
substring(line_str, space1 + 1, space2);
499 status_code = atoi(status_c);