Skip to content

Commit

Permalink
lib-http: client: Send empty payload (Content-Length: 0) for requests…
Browse files Browse the repository at this point in the history
… that normally expect a payload.

This includes the standard POST and PUT methods.
Others need to use the new http_client_request_set_payload_empty() function to force sending an empty payload.
  • Loading branch information
stephanbosch committed Sep 21, 2017
1 parent 7e37e7a commit 4d1cc68
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/lib-http/http-client-private.h
Expand Up @@ -134,6 +134,7 @@ struct http_client_request {
bool payload_sync_continue:1;
bool payload_chunked:1;
bool payload_wait:1;
bool payload_empty:1;
bool urgent:1;
bool submitted:1;
bool listed:1;
Expand Down
38 changes: 24 additions & 14 deletions src/lib-http/http-client-request.c
Expand Up @@ -461,6 +461,11 @@ void http_client_request_set_payload_data(struct http_client_request *req,
i_stream_unref(&input);
}

void http_client_request_set_payload_empty(struct http_client_request *req)
{
req->payload_empty = TRUE;
}

void http_client_request_set_timeout_msecs(struct http_client_request *req,
unsigned int msecs)
{
Expand Down Expand Up @@ -1152,20 +1157,25 @@ static int http_client_request_send_real(struct http_client_request *req,
if (!req->have_hdr_expect && req->payload_sync) {
str_append(rtext, "Expect: 100-continue\r\n");
}
if (req->payload_input != NULL) {
if (req->payload_chunked) {
// FIXME: can't do this for a HTTP/1.0 server
if (!req->have_hdr_body_spec)
str_append(rtext, "Transfer-Encoding: chunked\r\n");
req->payload_output =
http_transfer_chunked_ostream_create(output);
} else {
/* send Content-Length if we have specified a payload,
even if it's 0 bytes. */
if (!req->have_hdr_body_spec) {
str_printfa(rtext, "Content-Length: %"PRIuUOFF_T"\r\n",
req->payload_size);
}
if (req->payload_input != NULL && req->payload_chunked) {
// FIXME: can't do this for a HTTP/1.0 server
if (!req->have_hdr_body_spec)
str_append(rtext, "Transfer-Encoding: chunked\r\n");
req->payload_output =
http_transfer_chunked_ostream_create(output);
} else if (req->payload_input != NULL ||
req->payload_empty ||
strcasecmp(req->method, "POST") == 0 ||
strcasecmp(req->method, "PUT") == 0) {

/* send Content-Length if we have specified a payload
or when one is normally expected, even if it's 0 bytes. */
i_assert(req->payload_input != NULL || req->payload_size == 0);
if (!req->have_hdr_body_spec) {
str_printfa(rtext, "Content-Length: %"PRIuUOFF_T"\r\n",
req->payload_size);
}
if (req->payload_input != NULL) {
req->payload_output = output;
o_stream_ref(output);
}
Expand Down
5 changes: 5 additions & 0 deletions src/lib-http/http-client.h
Expand Up @@ -308,6 +308,11 @@ void http_client_request_set_payload(struct http_client_request *req,
*/
void http_client_request_set_payload_data(struct http_client_request *req,
const unsigned char *data, size_t size);
/* send an empty payload for this request. This means that a Content-Length
header is generated with zero size. Calling this function is not necessary
for the standard POST and PUT methods, for which this is done implicitly if
there is no payload set. */
void http_client_request_set_payload_empty(struct http_client_request *req);

/* set an absolute timeout for this request specifically, overriding the
default client-wide absolute request timeout */
Expand Down

0 comments on commit 4d1cc68

Please sign in to comment.