Skip to content

Commit

Permalink
net: http_client: Fix payload issue on HTTP upload
Browse files Browse the repository at this point in the history
Bug fix and improved `payload` handling in `http_client_req`.

Changes to `http_client_req` behaviour:

If the user provides `payload_len` it is used to generate the
`Content-Length` header. This is done even if `payload_cb` is used to
provide the actual data. If no `payload_len` is specified then no
`Content-Length` is generated.

If `payload_cb` is provided it is called to send the payload data.
Otherwise `payload` is used as the payload buffer and sent. If
`payload_len` is not zero, it is used as the size of `payload`.
Otherwise `payload` is assumed to be a string and `strlen` is used to
determine its size. This is to maintain current behaviour and not break
existing samples.

Fixes #24431

Signed-off-by: Arvin Farahmand <arvinf@ip-logix.com>
  • Loading branch information
arvinf authored and jukkar committed Apr 20, 2020
1 parent e241de8 commit 6d5f3de
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 31 deletions.
4 changes: 3 additions & 1 deletion include/net/http_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,9 @@ struct http_request {
/** Payload, may be NULL */
const char *payload;

/** Payload length, may be 0. Only used if payload field is not NULL */
/** Payload length is used to calculate Content-Length. Set to 0
* for chunked transfers.
*/
size_t payload_len;

/** User supplied callback function to call when optional headers need
Expand Down
67 changes: 37 additions & 30 deletions subsys/net/lib/http/http_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,9 +568,26 @@ int http_client_req(int sock, struct http_request *req,
total_sent += ret;
}

if (req->payload_cb) {
ret = http_send_data(sock, send_buf, send_buf_max_len,
if (req->payload || req->payload_cb) {
if (req->payload_len) {
char content_len_str[HTTP_CONTENT_LEN_SIZE];

ret = snprintk(content_len_str, HTTP_CONTENT_LEN_SIZE,
"%zd", req->payload_len);
if (ret <= 0 || ret >= HTTP_CONTENT_LEN_SIZE) {
ret = -ENOMEM;
goto out;
}

ret = http_send_data(sock, send_buf, send_buf_max_len,
&send_buf_pos, "Content-Length", ": ",
content_len_str, HTTP_CRLF,
HTTP_CRLF, NULL);
} else {
ret = http_send_data(sock, send_buf, send_buf_max_len,
&send_buf_pos, HTTP_CRLF, NULL);
}

if (ret < 0) {
goto out;
}
Expand All @@ -585,39 +602,29 @@ int http_client_req(int sock, struct http_request *req,
send_buf_pos = 0;
total_sent += ret;

ret = req->payload_cb(sock, req, user_data);
if (ret < 0) {
goto out;
}

total_sent += ret;
} else if (req->payload) {
char content_len_str[HTTP_CONTENT_LEN_SIZE];
if (req->payload_cb) {
ret = req->payload_cb(sock, req, user_data);
if (ret < 0) {
goto out;
}

ret = snprintk(content_len_str, HTTP_CONTENT_LEN_SIZE,
"%zd", req->payload_len);
if (ret <= 0 || ret >= HTTP_CONTENT_LEN_SIZE) {
ret = -ENOMEM;
goto out;
}
total_sent += ret;
} else {
u32_t length;

ret = http_send_data(sock, send_buf, send_buf_max_len,
&send_buf_pos, "Content-Length", ": ",
content_len_str, HTTP_CRLF,
HTTP_CRLF, NULL);
if (ret < 0) {
goto out;
}
if (req->payload_len == 0) {
length = strlen(req->payload);
} else {
length = req->payload_len;
}

total_sent += ret;
ret = sendall(sock, req->payload, length);
if (ret < 0) {
goto out;
}

ret = http_send_data(sock, send_buf, send_buf_max_len,
&send_buf_pos, req->payload, NULL);
if (ret < 0) {
goto out;
total_sent += length;
}

total_sent += ret;
} else {
ret = http_send_data(sock, send_buf, send_buf_max_len,
&send_buf_pos, HTTP_CRLF, NULL);
Expand Down

0 comments on commit 6d5f3de

Please sign in to comment.