Browse Source

net: lib: http_client: Fix end of message detection

HTTP 1.1 server has two ways of indicating the message body length -
either by providing the Content Length header, or by closing the
connection when the entire body has been transmitted.

The second method didn't work with Zephyr's HTTP client implementation,
as EOF on a socket was treated as an error condition. Therefore, if no
Content Length was provided by the server, such transfers would always
end up with ECONNRESET error.

In order to fix this, we need to notify the parser about the EOF on a
socket when connection is closed. It is the parser role to determine
whether the EOF was expected in current state (by marking end of message
flag) or not (by setting an error).

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
pull/92793/head
Robert Lubos 6 days ago committed by Daniel DeGrasse
parent
commit
8f983ccda5
  1. 9
      subsys/net/lib/http/http_client.c

9
subsys/net/lib/http/http_client.c

@ -520,8 +520,8 @@ static int http_wait_data(int sock, struct http_request *req, const k_timepoint_ @@ -520,8 +520,8 @@ static int http_wait_data(int sock, struct http_request *req, const k_timepoint_
} else if (fds[0].revents & ZSOCK_POLLIN) {
received = zsock_recv(sock, req->internal.response.recv_buf + offset,
req->internal.response.recv_buf_len - offset, 0);
if (received == 0) {
/* Connection closed */
if (received == 0 && total_received == 0) {
/* Connection closed, no data received */
goto closed;
} else if (received < 0) {
ret = -errno;
@ -534,9 +534,12 @@ static int http_wait_data(int sock, struct http_request *req, const k_timepoint_ @@ -534,9 +534,12 @@ static int http_wait_data(int sock, struct http_request *req, const k_timepoint_
/* Initialize the data length with the received data length. */
req->internal.response.data_len = offset;
/* In case of EOF on a socket, indicate this by passing
* 0 length to the parser.
*/
processed = http_parser_execute(
&req->internal.parser, &req->internal.parser_settings,
req->internal.response.recv_buf, offset);
req->internal.response.recv_buf, received > 0 ? offset : 0);
if (processed > offset) {
LOG_ERR("HTTP parser error, too much data consumed");

Loading…
Cancel
Save