# HG changeset patch # User Stephan Bosch # Date 1505947113 -7200 # Node ID 2cd3df7171e151b4d5a1de35d341db7e26391fa1 # Parent fea53c2725c094a4ea9265121a346237bb69e280 lib-http: client: Send empty payload (Content-Length: 0) for requests 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. diff -r fea53c2725c0 -r 2cd3df7171e1 src/lib-http/http-client-private.h --- a/src/lib-http/http-client-private.h Thu Nov 09 12:24:16 2017 +0200 +++ b/src/lib-http/http-client-private.h Thu Sep 21 00:38:33 2017 +0200 @@ -134,6 +134,7 @@ unsigned int payload_sync_continue:1; unsigned int payload_chunked:1; unsigned int payload_wait:1; + unsigned int payload_empty:1; unsigned int urgent:1; unsigned int submitted:1; unsigned int listed:1; diff -r fea53c2725c0 -r 2cd3df7171e1 src/lib-http/http-client-request.c --- a/src/lib-http/http-client-request.c Thu Nov 09 12:24:16 2017 +0200 +++ b/src/lib-http/http-client-request.c Thu Sep 21 00:38:33 2017 +0200 @@ -463,6 +463,11 @@ 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) { @@ -1161,20 +1166,25 @@ 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); } diff -r fea53c2725c0 -r 2cd3df7171e1 src/lib-http/http-client.h --- a/src/lib-http/http-client.h Thu Nov 09 12:24:16 2017 +0200 +++ b/src/lib-http/http-client.h Thu Sep 21 00:38:33 2017 +0200 @@ -311,6 +311,11 @@ */ 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 */