[libsoup/carlosgc/request-body-no-content-type] soup-message: Allow to pass a NULL content type to soup_message_set_request_body




commit c44a4eb070a7559d453fdd300670a2eddacce70b
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Wed Jan 27 10:48:04 2021 +0100

    soup-message: Allow to pass a NULL content type to soup_message_set_request_body
    
    If it's unknown or has already been set in headers. It was already
    possible in libsoup 2 API just by setting the request body directly
    instead of using the convenient API.

 libsoup/soup-message.c    | 48 +++++++++++++++++++++++++----------------------
 tests/request-body-test.c | 31 ++++++++++++++++++++++--------
 2 files changed, 49 insertions(+), 30 deletions(-)
---
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index afac1a1e..9b2bda0a 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -911,12 +911,13 @@ soup_message_new_from_multipart (const char    *uri_string,
 /**
  * soup_message_set_request_body:
  * @msg: the message
- * @content_type: (allow-none): MIME Content-Type of the body
+ * @content_type: (allow-none): MIME Content-Type of the body, or %NULL if unknown
  * @stream: (allow-none): a #GInputStream to read the request body from
- * @content_length: the byte length of @tream or -1 if unknown
+ * @content_length: the byte length of @stream or -1 if unknown
  *
- * Set the request body of a #SoupMessage. If
- * @content_type is %NULL, the request body must be empty (or @stream %NULL) as well.
+ * Set the request body of a #SoupMessage.
+ * If @content_type is %NULL and @stream is not %NULL the Content-Type header will
+ * not be changed if present.
  * The request body needs to be set again in case @msg is restarted
  * (in case of redirection or authentication).
  */
@@ -927,22 +928,26 @@ soup_message_set_request_body (SoupMessage  *msg,
                                gssize        content_length)
 {
         g_return_if_fail (SOUP_IS_MESSAGE (msg));
-        g_return_if_fail (content_type != NULL || content_length == 0);
-        g_return_if_fail (content_type == NULL || G_IS_INPUT_STREAM (stream));
+        g_return_if_fail (stream == NULL || G_IS_INPUT_STREAM (stream));
+        g_return_if_fail (content_length == -1 || content_length >= 0);
 
         SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
 
         g_clear_object (&priv->request_body_stream);
 
-        if (content_type) {
-                g_warn_if_fail (strchr (content_type, '/') != NULL);
+        if (stream) {
+                if (content_type) {
+                        g_warn_if_fail (strchr (content_type, '/') != NULL);
+
+                        if (soup_message_headers_get_content_type (priv->request_headers, NULL) != 
content_type)
+                                soup_message_headers_replace (priv->request_headers, "Content-Type", 
content_type);
+                }
 
-                if (soup_message_headers_get_content_type (priv->request_headers, NULL) != content_type)
-                        soup_message_headers_replace (priv->request_headers, "Content-Type", content_type);
                 if (content_length == -1)
                         soup_message_headers_set_encoding (priv->request_headers, SOUP_ENCODING_CHUNKED);
                 else
                         soup_message_headers_set_content_length (priv->request_headers, content_length);
+
                 priv->request_body_stream = g_object_ref (stream);
         } else {
                 soup_message_headers_remove (priv->request_headers, "Content-Type");
@@ -953,11 +958,12 @@ soup_message_set_request_body (SoupMessage  *msg,
 /**
  * soup_message_set_request_body_from_bytes:
  * @msg: the message
- * @content_type: (allow-none): MIME Content-Type of the body
+ * @content_type: (allow-none): MIME Content-Type of the body, or %NULL if unknown
  * @bytes: (allow-none): a #GBytes with the request body data
  *
- * Set the request body of a #SoupMessage from #GBytes. If
- * @content_type is %NULL, the request body must be empty (or @bytes %NULL) as well.
+ * Set the request body of a #SoupMessage from #GBytes.
+ * If @content_type is %NULL and @bytes is not %NULL the Content-Type header will
+ * not be changed if present.
  * The request body needs to be set again in case @msg is restarted
  * (in case of redirection or authentication).
  */
@@ -967,17 +973,15 @@ soup_message_set_request_body_from_bytes (SoupMessage  *msg,
                                           GBytes       *bytes)
 {
         g_return_if_fail (SOUP_IS_MESSAGE (msg));
-        g_return_if_fail (content_type == NULL || bytes != NULL);
-        g_return_if_fail (content_type != NULL || g_bytes_get_size (bytes) == 0);
 
-       if (bytes) {
-               GInputStream *stream;
+        if (bytes) {
+                GInputStream *stream;
 
-               stream = g_memory_input_stream_new_from_bytes (bytes);
-               soup_message_set_request_body (msg, content_type, stream, g_bytes_get_size (bytes));
-               g_object_unref (stream);
-       } else
-               soup_message_set_request_body (msg, NULL, NULL, 0);
+                stream = g_memory_input_stream_new_from_bytes (bytes);
+                soup_message_set_request_body (msg, content_type, stream, g_bytes_get_size (bytes));
+                g_object_unref (stream);
+        } else
+                soup_message_set_request_body (msg, NULL, NULL, 0);
 }
 
 void
diff --git a/tests/request-body-test.c b/tests/request-body-test.c
index aa49f9a9..091633a9 100644
--- a/tests/request-body-test.c
+++ b/tests/request-body-test.c
@@ -14,6 +14,7 @@ typedef struct {
         SoupSession *session;
         GInputStream *stream;
         GBytes *bytes;
+        const char *content_type;
         int nwrote;
 } PutTestData;
 
@@ -22,12 +23,13 @@ typedef enum {
         RESTART = 1 << 1,
         ASYNC = 1 << 2,
         LARGE = 1 << 3,
-        EMPTY = 1 << 4
+        EMPTY = 1 << 4,
+        NO_CONTENT_TYPE = 1 << 5,
 } RequestTestFlags;
 
 static void
 wrote_body_data (SoupMessage *msg,
-                guint        count,
+                 guint        count,
                  PutTestData *ptd)
 {
         debug_printf (2, "  wrote_body_data, %u bytes\n", count);
@@ -61,6 +63,7 @@ setup_request_body (PutTestData     *ptd,
                 g_checksum_update (check, (guchar *)data, strlen (data));
         }
         ptd->stream = flags & BYTES ? NULL : g_memory_input_stream_new_from_bytes (ptd->bytes);
+        ptd->content_type = flags & NO_CONTENT_TYPE ? NULL : "text/plain";
 
         return check;
 }
@@ -79,9 +82,9 @@ restarted (SoupMessage *msg,
         if (ptd->stream) {
                 g_object_unref (ptd->stream);
                 ptd->stream = g_memory_input_stream_new_from_bytes (ptd->bytes);
-                soup_message_set_request_body (msg, "text/plain", ptd->stream, -1);
+                soup_message_set_request_body (msg, ptd->content_type, ptd->stream, -1);
         } else {
-                soup_message_set_request_body_from_bytes (msg, "text/plain", ptd->bytes);
+                soup_message_set_request_body_from_bytes (msg, ptd->content_type, ptd->bytes);
         }
 }
 
@@ -92,6 +95,7 @@ do_request_test (gconstpointer data)
         GUri *uri;
         PutTestData ptd;
         SoupMessage *msg;
+        SoupMessageHeaders *request_headers;
         const char *client_md5, *server_md5;
         GChecksum *check;
 
@@ -105,10 +109,17 @@ do_request_test (gconstpointer data)
         client_md5 = g_checksum_get_string (check);
 
         msg = soup_message_new_from_uri ("PUT", uri);
-        if (flags & BYTES)
-                soup_message_set_request_body_from_bytes (msg, flags & EMPTY ? NULL : "text/plain", 
ptd.bytes);
-        else
-                soup_message_set_request_body (msg, "text/plain", ptd.stream, -1);
+        request_headers = soup_message_get_request_headers (msg);
+        if (flags & BYTES) {
+                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 {
+                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);
+        }
+        g_assert_cmpstr (soup_message_headers_get_one (request_headers, "Content-Type"), ==, 
ptd.content_type);
 
         if (flags & RESTART) {
                 g_signal_connect (msg, "restarted",
@@ -191,12 +202,16 @@ main (int argc, char **argv)
         g_test_add_data_func ("/request-body/sync/restart-bytes", GINT_TO_POINTER (RESTART | BYTES), 
do_request_test);
         g_test_add_data_func ("/request-body/sync/large", GINT_TO_POINTER (BYTES | LARGE), do_request_test);
         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/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);
         g_test_add_data_func ("/request-body/async/restart-bytes", GINT_TO_POINTER (RESTART | ASYNC | 
BYTES), do_request_test);
         g_test_add_data_func ("/request-body/async/large", GINT_TO_POINTER (BYTES | LARGE | ASYNC), 
do_request_test);
         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);
 
         ret = g_test_run ();
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]