summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2021-02-03 15:54:38 +0100
committerCarlos Garcia Campos <cgarcia@igalia.com>2021-02-03 15:54:38 +0100
commitdde1a85cf5f8bfb042e6c47530c82b5c6c40353e (patch)
treed3d573662edaa43952197a806999b125db017783
parentac985daae31def82869ac60ef1e9f2ebf3fd259f (diff)
downloadlibsoup-carlosgc/null-post-content-length.tar.gz
session: Include Content-Length header for put and post requests with no bodycarlosgc/null-post-content-length
As suggested in the HTTP spec.
-rw-r--r--libsoup/soup-session.c13
-rw-r--r--tests/request-body-test.c24
2 files changed, 33 insertions, 4 deletions
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index d867684a..4509993a 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1006,6 +1006,7 @@ soup_session_send_queue_item (SoupSession *session,
{
SoupSessionPrivate *priv = soup_session_get_instance_private (session);
SoupMessageHeaders *request_headers;
+ const char *method;
request_headers = soup_message_get_request_headers (item->msg);
if (priv->user_agent)
@@ -1042,6 +1043,18 @@ soup_session_send_queue_item (SoupSession *session,
g_free (host);
}
+ /* A user agent SHOULD send a Content-Length in a request message when
+ * no Transfer-Encoding is sent and the request method defines a meaning
+ * for an enclosed payload body. For example, a Content-Length header
+ * field is normally sent in a POST request even when the value is 0
+ * (indicating an empty payload body).
+ */
+ method = soup_message_get_method (item->msg);
+ if ((method == SOUP_METHOD_POST || method == SOUP_METHOD_PUT) &&
+ soup_message_get_request_body_stream (item->msg) == NULL) {
+ soup_message_headers_set_content_length (request_headers, 0);
+ }
+
soup_message_starting (item->msg);
if (item->state == SOUP_MESSAGE_RUNNING)
soup_connection_send_request (item->conn, item, completion_cb, item);
diff --git a/tests/request-body-test.c b/tests/request-body-test.c
index 091633a9..e5d9ffa1 100644
--- a/tests/request-body-test.c
+++ b/tests/request-body-test.c
@@ -25,6 +25,7 @@ typedef enum {
LARGE = 1 << 3,
EMPTY = 1 << 4,
NO_CONTENT_TYPE = 1 << 5,
+ NULL_STREAM = 1 << 6,
} RequestTestFlags;
static void
@@ -44,6 +45,14 @@ setup_request_body (PutTestData *ptd,
ptd->nwrote = 0;
check = g_checksum_new (G_CHECKSUM_MD5);
+ if (flags & NULL_STREAM) {
+ ptd->bytes = NULL;
+ ptd->stream = NULL;
+ ptd->content_type = NULL;
+
+ return check;
+ }
+
if (flags & LARGE) {
static const unsigned int large_size = 1000000;
char *large_data;
@@ -83,7 +92,7 @@ restarted (SoupMessage *msg,
g_object_unref (ptd->stream);
ptd->stream = g_memory_input_stream_new_from_bytes (ptd->bytes);
soup_message_set_request_body (msg, ptd->content_type, ptd->stream, -1);
- } else {
+ } else if (ptd->bytes) {
soup_message_set_request_body_from_bytes (msg, ptd->content_type, ptd->bytes);
}
}
@@ -114,7 +123,7 @@ do_request_test (gconstpointer data)
soup_message_set_request_body_from_bytes (msg, ptd.content_type, ptd.bytes);
g_assert_cmpuint (soup_message_headers_get_content_length (request_headers), ==, g_bytes_get_size (ptd.bytes));
g_assert_true (soup_message_headers_get_encoding (request_headers) == SOUP_ENCODING_CONTENT_LENGTH);
- } else {
+ } else if (!(flags & NULL_STREAM)) {
soup_message_set_request_body (msg, ptd.content_type, ptd.stream, -1);
g_assert_cmpuint (soup_message_headers_get_content_length (request_headers), ==, 0);
g_assert_true (soup_message_headers_get_encoding (request_headers) == SOUP_ENCODING_CHUNKED);
@@ -134,13 +143,18 @@ do_request_test (gconstpointer data)
else
soup_test_session_send_message (session, msg);
soup_test_assert_message_status (msg, SOUP_STATUS_CREATED);
- g_assert_cmpint (g_bytes_get_size (ptd.bytes), ==, ptd.nwrote);
+ if (flags & NULL_STREAM) {
+ g_assert_cmpint (ptd.nwrote, ==, 0);
+ g_assert_cmpstr (soup_message_headers_get_one (request_headers, "Content-Length"), ==, "0");
+ } else {
+ g_assert_cmpint (g_bytes_get_size (ptd.bytes), ==, ptd.nwrote);
+ }
server_md5 = soup_message_headers_get_one (soup_message_get_response_headers (msg),
"Content-MD5");
g_assert_cmpstr (client_md5, ==, server_md5);
- g_bytes_unref (ptd.bytes);
+ g_clear_pointer (&ptd.bytes, g_bytes_unref);
g_clear_object (&ptd.stream);
g_object_unref (msg);
g_checksum_free (check);
@@ -204,6 +218,7 @@ main (int argc, char **argv)
g_test_add_data_func ("/request-body/sync/empty", GINT_TO_POINTER (BYTES | EMPTY), do_request_test);
g_test_add_data_func ("/request-body/sync/no-content-type-stream", GINT_TO_POINTER (NO_CONTENT_TYPE), do_request_test);
g_test_add_data_func ("/request-body/sync/no-content-type-bytes", GINT_TO_POINTER (BYTES | NO_CONTENT_TYPE), do_request_test);
+ g_test_add_data_func ("/request-body/sync/null", GINT_TO_POINTER (NULL_STREAM), do_request_test);
g_test_add_data_func ("/request-body/async/stream", GINT_TO_POINTER (ASYNC), do_request_test);
g_test_add_data_func ("/request-body/async/bytes", GINT_TO_POINTER (BYTES | ASYNC), do_request_test);
g_test_add_data_func ("/request-body/async/restart-stream", GINT_TO_POINTER (RESTART | ASYNC), do_request_test);
@@ -212,6 +227,7 @@ main (int argc, char **argv)
g_test_add_data_func ("/request-body/async/empty", GINT_TO_POINTER (BYTES | EMPTY | ASYNC), do_request_test);
g_test_add_data_func ("/request-body/async/no-content-type-stream", GINT_TO_POINTER (NO_CONTENT_TYPE | ASYNC), do_request_test);
g_test_add_data_func ("/request-body/async/no-content-type-bytes", GINT_TO_POINTER (BYTES | NO_CONTENT_TYPE | ASYNC), do_request_test);
+ g_test_add_data_func ("/request-body/async/null", GINT_TO_POINTER (NULL_STREAM | ASYNC), do_request_test);
ret = g_test_run ();