[libsoup] Fix the handling of trailing junk with Content-Encoding



commit cdddef93f1c63fbe2a24aa8a2ccc95c083f3750f
Author: Dan Winship <danw gnome org>
Date:   Thu May 24 14:52:52 2012 -0400

    Fix the handling of trailing junk with Content-Encoding
    
    When a content-encoded response has trailing junk,
    SoupConverterWrapper needs to make sure that all of that junk gets
    read before returning G_CONVERTER_FINISHED, or else it will end up
    becoming the start of the next response on that connection.
    
    coding-test wasn't hitting this, because the trailing junk was always
    small enough that it would have been read into GConverterInputStream's
    internal buffer already at the point when the GZlibDecompresser
    returned FINISHED. Switching coding-test to use chunked encoding
    caused it to reliably hit the bug though, because the final 0-length
    chunk (including its header) will always still be unread at that
    point. So update it to use that.
    
    Also add a SoupRequest-based test to coding-test, though it turns out
    to not have been relevant to this bug, which affected the SoupMessage
    API too.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=676477

 libsoup/soup-converter-wrapper.c |   57 ++++++-
 tests/coding-test.c              |  303 ++++++++++++++++++++++++++++++++++----
 2 files changed, 319 insertions(+), 41 deletions(-)
---
diff --git a/libsoup/soup-converter-wrapper.c b/libsoup/soup-converter-wrapper.c
index 8480960..4160c5f 100644
--- a/libsoup/soup-converter-wrapper.c
+++ b/libsoup/soup-converter-wrapper.c
@@ -15,10 +15,12 @@
 #include "soup-message.h"
 
 /* SoupConverterWrapper is a GConverter that wraps another GConverter.
- * Mostly it is transparent, but it implements two special fallbacks
+ * Mostly it is transparent, but it implements three special fallbacks
  * for Content-Encoding handling: (1) "deflate" can mean either raw
  * deflate or zlib-encoded default, (2) the server may mistakenly
- * claim that a response is encoded when actually it isn't.
+ * claim that a response is encoded when actually it isn't, (3) the
+ * response may contain trailing junk after the end of the encoded
+ * portion that we want to ignore.
  *
  * If the wrapped conversion succeeds, then the wrapper will set the
  * %SOUP_MESSAGE_CONTENT_DECODED flag on its message.
@@ -42,6 +44,7 @@ struct _SoupConverterWrapperPrivate
 	SoupMessage *msg;
 	gboolean try_deflate_fallback;
 	gboolean started;
+	gboolean discarding;
 };
 
 static void
@@ -180,25 +183,42 @@ soup_converter_wrapper_fallback_convert (GConverter *converter,
 					 gsize      *bytes_written,
 					 GError    **error)
 {
+	SoupConverterWrapperPrivate *priv = SOUP_CONVERTER_WRAPPER (converter)->priv;
+
 	if (outbuf_size == 0) {
 		g_set_error (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
 			     _("Output buffer is too small"));
 		return G_CONVERTER_ERROR;
 	}
 
-	if (outbuf_size >= inbuf_size) {
+	if (priv->discarding) {
+		*bytes_read = inbuf_size;
+		*bytes_written = 0;
+	} else if (outbuf_size >= inbuf_size) {
 		memcpy (outbuf, inbuf, inbuf_size);
 		*bytes_read = *bytes_written = inbuf_size;
-		if (flags & G_CONVERTER_INPUT_AT_END)
-			return G_CONVERTER_FINISHED;
-		else if (flags & G_CONVERTER_FLUSH)
-			return G_CONVERTER_FLUSHED;
-		else
-			return G_CONVERTER_CONVERTED;
 	} else {
 		memcpy (outbuf, inbuf, outbuf_size);
 		*bytes_read = *bytes_written = outbuf_size;
+	}
+
+	if (*bytes_read < inbuf_size)
+		return G_CONVERTER_CONVERTED;
+
+	if (flags & G_CONVERTER_INPUT_AT_END)
+		return G_CONVERTER_FINISHED;
+	else if (flags & G_CONVERTER_FLUSH)
+		return G_CONVERTER_FLUSHED;
+	else if (inbuf_size)
 		return G_CONVERTER_CONVERTED;
+	else {
+		/* Force it to either read more input or
+		 * try again with G_CONVERTER_INPUT_AT_END.
+		 */
+		g_set_error_literal (error, G_IO_ERROR,
+				     G_IO_ERROR_PARTIAL_INPUT,
+				     "");
+		return G_CONVERTER_ERROR;
 	}
 }
 
@@ -229,6 +249,25 @@ soup_converter_wrapper_real_convert (GConverter *converter,
 			soup_message_set_flags (priv->msg, flags | SOUP_MESSAGE_CONTENT_DECODED);
 			priv->started = TRUE;
 		}
+
+		if (result == G_CONVERTER_FINISHED &&
+		    !(flags & G_CONVERTER_INPUT_AT_END)) {
+			/* We need to keep reading (and discarding)
+			 * input to the end of the message body.
+			 */
+			g_clear_object (&priv->base_converter);
+			priv->discarding = TRUE;
+
+			if (*bytes_written)
+				return G_CONVERTER_CONVERTED;
+			else {
+				g_set_error_literal (error, G_IO_ERROR,
+						     G_IO_ERROR_PARTIAL_INPUT,
+						     "");
+				return G_CONVERTER_ERROR;
+			}
+		}
+
 		return result;
 	}
 
diff --git a/tests/coding-test.c b/tests/coding-test.c
index 2ac0373..ea8b857 100644
--- a/tests/coding-test.c
+++ b/tests/coding-test.c
@@ -15,7 +15,11 @@
 #include <unistd.h>
 
 #include <glib.h>
+
+#define LIBSOUP_USE_UNSTABLE_REQUEST_API
 #include <libsoup/soup.h>
+#include <libsoup/soup-requester.h>
+#include <libsoup/soup-request-http.h>
 
 #include "test-utils.h"
 
@@ -117,6 +121,8 @@ server_callback (SoupServer *server, SoupMessage *msg,
 	}
 
 	soup_message_set_status (msg, SOUP_STATUS_OK);
+	soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CHUNKED);
+
 	soup_message_body_append (msg->response_body,
 				  SOUP_MEMORY_TAKE, contents, length);
 
@@ -124,6 +130,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
 		soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY,
 					  options, strlen (options));
 	}
+	soup_message_body_complete (msg->response_body);
 }
 
 typedef enum {
@@ -133,50 +140,51 @@ typedef enum {
 } MessageContentStatus;
 
 static void
-do_single_coding_test (SoupSession *session,
-		       SoupMessage *msg,
-		       const char *expected_encoding,
-		       const char *expected_content_type,
-		       MessageContentStatus status)
+check_response (SoupMessage *msg,
+		const char *expected_encoding,
+		const char *expected_content_type,
+		MessageContentStatus status)
 {
 	const char *coding, *type;
 
-	soup_session_send_message (session, msg);
 	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-		debug_printf (1, "  Unexpected status %d %s\n",
+		debug_printf (1, "    Unexpected status %d %s\n",
 			      msg->status_code, msg->reason_phrase);
 		errors++;
 	}
+
 	coding = soup_message_headers_get_one (msg->response_headers, "Content-Encoding");
 	if (expected_encoding) {
 		if (!coding || g_ascii_strcasecmp (coding, expected_encoding) != 0) {
-			debug_printf (1, "  Unexpected Content-Encoding: %s\n",
+			debug_printf (1, "    Unexpected Content-Encoding: %s\n",
 				      coding ? coding : "(none)");
 			errors++;
 		}
 	} else {
 		if (coding) {
-			debug_printf (1, "  Unexpected Content-Encoding: %s\n",
+			debug_printf (1, "    Unexpected Content-Encoding: %s\n",
 				      coding);
 			errors++;
 		}
 	}
+
 	if (status != NO_CHECK) {
 		if (status == EXPECT_DECODED) {
 			if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED)) {
-				debug_printf (1, "  SOUP_MESSAGE_CONTENT_DECODED not set!\n");
+				debug_printf (1, "    SOUP_MESSAGE_CONTENT_DECODED not set!\n");
 				errors++;
 			}
 		} else {
 			if (soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED) {
-				debug_printf (1, "  SOUP_MESSAGE_CONTENT_DECODED set!\n");
+				debug_printf (1, "    SOUP_MESSAGE_CONTENT_DECODED set!\n");
 				errors++;
 			}
 		}
 	}
+
 	type = soup_message_headers_get_one (msg->response_headers, "Content-Type");
 	if (!type || g_ascii_strcasecmp (type, expected_content_type) != 0) {
-		debug_printf (1, "  Unexpected Content-Type: %s\n",
+		debug_printf (1, "    Unexpected Content-Type: %s\n",
 			      type ? type : "(none)");
 		errors++;
 	}
@@ -189,7 +197,7 @@ check_msg_bodies (SoupMessage *msg1,
 		  const char *msg2_type)
 {
 	if (msg1->response_body->length != msg2->response_body->length) {
-		debug_printf (1, "  Message length mismatch: %lu (%s) vs %lu (%s)\n",
+		debug_printf (1, "    Message length mismatch: %lu (%s) vs %lu (%s)\n",
 			      (gulong)msg1->response_body->length,
 			      msg1_type,
 			      (gulong)msg2->response_body->length,
@@ -198,7 +206,7 @@ check_msg_bodies (SoupMessage *msg1,
 	} else if (memcmp (msg1->response_body->data,
 			   msg2->response_body->data,
 			   msg1->response_body->length) != 0) {
-		debug_printf (1, "  Message data mismatch (%s/%s)\n",
+		debug_printf (1, "    Message data mismatch (%s/%s)\n",
 			      msg1_type, msg2_type);
 		errors++;
 	}
@@ -211,35 +219,41 @@ do_coding_test (void)
 	SoupMessage *msg, *msgz, *msgj, *msge, *msgzl, *msgzlj, *msgzle, *msgzlr, *msgzlre;
 	SoupURI *uri;
 
+	debug_printf (1, "SoupMessage tests\n");
+
 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
 	uri = soup_uri_new_with_base (base_uri, "/mbox");
 
 	/* Plain text data, no claim */
-	debug_printf (1, "GET /mbox, plain\n");
+	debug_printf (1, "  GET /mbox, plain\n");
 	msg = soup_message_new_from_uri ("GET", uri);
-	do_single_coding_test (session, msg, NULL, "text/plain", EXPECT_NOT_DECODED);
+	soup_session_send_message (session, msg);
+	check_response (msg, NULL, "text/plain", EXPECT_NOT_DECODED);
 
 	/* Plain text data, claim gzip */
-	debug_printf (1, "GET /mbox, Accept-Encoding: gzip\n");
+	debug_printf (1, "  GET /mbox, Accept-Encoding: gzip\n");
 	soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
 	msgz = soup_message_new_from_uri ("GET", uri);
-	do_single_coding_test (session, msgz, "gzip", "text/plain", EXPECT_DECODED);
+	soup_session_send_message (session, msgz);
+	check_response (msgz, "gzip", "text/plain", EXPECT_DECODED);
 	check_msg_bodies (msg, msgz, "plain", "compressed");
 
 	/* Plain text data, claim gzip w/ junk */
-	debug_printf (1, "GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
+	debug_printf (1, "  GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
 	msgj = soup_message_new_from_uri ("GET", uri);
 	soup_message_headers_append (msgj->request_headers,
 				     "X-Test-Options", "trailing-junk");
-	do_single_coding_test (session, msgj, "gzip", "text/plain", EXPECT_DECODED);
+	soup_session_send_message (session, msgj);
+	check_response (msgj, "gzip", "text/plain", EXPECT_DECODED);
 	check_msg_bodies (msg, msgj, "plain", "compressed w/ junk");
 
 	/* Plain text data, claim gzip with server error */
-	debug_printf (1, "GET /mbox, Accept-Encoding: gzip, with server error\n");
+	debug_printf (1, "  GET /mbox, Accept-Encoding: gzip, with server error\n");
 	msge = soup_message_new_from_uri ("GET", uri);
 	soup_message_headers_append (msge->request_headers,
 				     "X-Test-Options", "force-encode");
-	do_single_coding_test (session, msge, "gzip", "text/plain", EXPECT_NOT_DECODED);
+	soup_session_send_message (session, msge);
+	check_response (msge, "gzip", "text/plain", EXPECT_NOT_DECODED);
 
 	/* Failed content-decoding should have left the body untouched
 	 * from what the server sent... which happens to be the
@@ -248,43 +262,48 @@ do_coding_test (void)
 	check_msg_bodies (msg, msge, "plain", "mis-encoded");
 
 	/* Plain text data, claim deflate */
-	debug_printf (1, "GET /mbox, Accept-Encoding: deflate\n");
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate\n");
 	msgzl = soup_message_new_from_uri ("GET", uri);
 	soup_message_headers_append (msgzl->request_headers,
 				     "X-Test-Options", "prefer-deflate-zlib");
-	do_single_coding_test (session, msgzl, "deflate", "text/plain", EXPECT_DECODED);
+	soup_session_send_message (session, msgzl);
+	check_response (msgzl, "deflate", "text/plain", EXPECT_DECODED);
 	check_msg_bodies (msg, msgzl, "plain", "compressed");
 
 	/* Plain text data, claim deflate w/ junk */
-	debug_printf (1, "GET /mbox, Accept-Encoding: deflate, plus trailing junk\n");
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate, plus trailing junk\n");
 	msgzlj = soup_message_new_from_uri ("GET", uri);
 	soup_message_headers_append (msgzlj->request_headers,
 				     "X-Test-Options", "prefer-deflate-zlib, trailing-junk");
-	do_single_coding_test (session, msgzlj, "deflate", "text/plain", EXPECT_DECODED);
+	soup_session_send_message (session, msgzlj);
+	check_response (msgzlj, "deflate", "text/plain", EXPECT_DECODED);
 	check_msg_bodies (msg, msgzlj, "plain", "compressed w/ junk");
 
 	/* Plain text data, claim deflate with server error */
-	debug_printf (1, "GET /mbox, Accept-Encoding: deflate, with server error\n");
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate, with server error\n");
 	msgzle = soup_message_new_from_uri ("GET", uri);
 	soup_message_headers_append (msgzle->request_headers,
 				     "X-Test-Options", "force-encode, prefer-deflate-zlib");
-	do_single_coding_test (session, msgzle, "deflate", "text/plain", EXPECT_NOT_DECODED);
+	soup_session_send_message (session, msgzle);
+	check_response (msgzle, "deflate", "text/plain", EXPECT_NOT_DECODED);
 	check_msg_bodies (msg, msgzle, "plain", "mis-encoded");
 
 	/* Plain text data, claim deflate (no zlib headers)*/
-	debug_printf (1, "GET /mbox, Accept-Encoding: deflate (raw data)\n");
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate (raw data)\n");
 	msgzlr = soup_message_new_from_uri ("GET", uri);
 	soup_message_headers_append (msgzlr->request_headers,
 				     "X-Test-Options", "prefer-deflate-raw");
-	do_single_coding_test (session, msgzlr, "deflate", "text/plain", EXPECT_DECODED);
+	soup_session_send_message (session, msgzlr);
+	check_response (msgzlr, "deflate", "text/plain", EXPECT_DECODED);
 	check_msg_bodies (msg, msgzlr, "plain", "compressed");
 
 	/* Plain text data, claim deflate with server error */
-	debug_printf (1, "GET /mbox, Accept-Encoding: deflate (raw data), with server error\n");
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate (raw data), with server error\n");
 	msgzlre = soup_message_new_from_uri ("GET", uri);
 	soup_message_headers_append (msgzlre->request_headers,
 				     "X-Test-Options", "force-encode, prefer-deflate-raw");
-	do_single_coding_test (session, msgzlre, "deflate", "text/plain", EXPECT_NOT_DECODED);
+	soup_session_send_message (session, msgzlre);
+	check_response (msgzlre, "deflate", "text/plain", EXPECT_NOT_DECODED);
 	check_msg_bodies (msg, msgzlre, "plain", "mis-encoded");
 
 	g_object_unref (msg);
@@ -301,6 +320,225 @@ do_coding_test (void)
 	soup_test_session_abort_unref (session);
 }
 
+static void
+req_sent (GObject *req, GAsyncResult *result, gpointer user_data)
+{
+	GInputStream **stream = user_data;
+	GError *error = NULL;
+
+	*stream = soup_request_send_finish (SOUP_REQUEST (req),
+					    result, &error);
+	if (error) {
+		debug_printf (1, "    Error sending request: %s\n",
+			      error->message);
+		g_error_free (error);
+		errors++;
+	}
+}
+
+static void
+read_finished (GObject *stream, GAsyncResult *result, gpointer user_data)
+{
+	gssize *nread = user_data;
+	GError *error = NULL;
+
+	*nread = g_input_stream_read_finish (G_INPUT_STREAM (stream),
+					     result, &error);
+	if (error) {
+		debug_printf (1, "    Error reading: %s\n",
+			      error->message);
+		g_error_free (error);
+		errors++;
+	}
+}
+
+static GByteArray *
+do_single_coding_req_test (SoupRequest *req,
+			   const char *expected_encoding,
+			   const char *expected_content_type,
+			   MessageContentStatus status)
+{
+	GInputStream *stream;
+	SoupMessage *msg;
+	GByteArray *data;
+	guchar buf[1024];
+	gssize nread;
+	GError *error = NULL;
+
+	msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+
+	stream = NULL;
+	soup_request_send_async (req, NULL, req_sent, &stream);
+	while (!stream)
+		g_main_context_iteration (NULL, TRUE);
+
+	data = g_byte_array_new ();
+	do {
+		nread = -2;
+		g_input_stream_read_async (stream, buf, sizeof (buf),
+					   G_PRIORITY_DEFAULT,
+					   NULL, read_finished, &nread);
+		while (nread == -2)
+			g_main_context_iteration (NULL, TRUE);
+
+		if (nread > 0)
+			g_byte_array_append (data, buf, nread);
+	} while (nread > 0);
+
+	g_input_stream_close (stream, NULL, &error);
+	if (error) {
+		debug_printf (1, "    error closing stream: %s\n",
+			      error->message);
+		g_error_free (error);
+		errors++;
+	}
+
+	check_response (msg, expected_encoding, expected_content_type, status);
+	g_object_unref (msg);
+
+	return data;
+}
+
+static void
+check_req_bodies (GByteArray *body1,
+		  GByteArray *body2,
+		  const char *msg1_type,
+		  const char *msg2_type)
+{
+	if (body1->len != body2->len) {
+		debug_printf (1, "    Message length mismatch: %lu (%s) vs %lu (%s)\n",
+			      (gulong)body1->len, msg1_type,
+			      (gulong)body2->len, msg2_type);
+		errors++;
+	} else if (memcmp (body1->data, body2->data, body1->len) != 0) {
+		debug_printf (1, "    Message data mismatch (%s/%s)\n",
+			      msg1_type, msg2_type);
+		errors++;
+	}
+}
+
+static void
+do_coding_req_test (void)
+{
+	SoupSession *session;
+	SoupRequester *requester;
+	SoupRequest *req;
+	SoupMessage *msg;
+	SoupURI *uri;
+	GByteArray *plain, *cmp;
+
+	debug_printf (1, "\nSoupRequest tests\n");
+
+	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+					 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+					 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
+					 NULL);
+	requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
+	uri = soup_uri_new_with_base (base_uri, "/mbox");
+
+	/* Plain text data, no claim */
+	debug_printf (1, "  GET /mbox, plain\n");
+	req = soup_requester_request_uri (requester, uri, NULL);
+	plain = do_single_coding_req_test (req, NULL, "text/plain", EXPECT_NOT_DECODED);
+	g_object_unref (req);
+
+	/* Plain text data, claim gzip */
+	debug_printf (1, "  GET /mbox, Accept-Encoding: gzip\n");
+	soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
+	req = soup_requester_request_uri (requester, uri, NULL);
+	cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED);
+	check_req_bodies (plain, cmp, "plain", "compressed");
+	g_byte_array_free (cmp, TRUE);
+	g_object_unref (req);
+
+	/* Plain text data, claim gzip w/ junk */
+	debug_printf (1, "  GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
+	req = soup_requester_request_uri (requester, uri, NULL);
+	msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+	soup_message_headers_append (msg->request_headers,
+				     "X-Test-Options", "trailing-junk");
+	cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED);
+	check_req_bodies (plain, cmp, "plain", "compressed w/ junk");
+	g_byte_array_free (cmp, TRUE);
+	g_object_unref (req);
+
+	/* Plain text data, claim gzip with server error */
+	debug_printf (1, "  GET /mbox, Accept-Encoding: gzip, with server error\n");
+	req = soup_requester_request_uri (requester, uri, NULL);
+	msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+	soup_message_headers_append (msg->request_headers,
+				     "X-Test-Options", "force-encode");
+	cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_NOT_DECODED);
+
+	/* Failed content-decoding should have left the body untouched
+	 * from what the server sent... which happens to be the
+	 * uncompressed data.
+	 */
+	check_req_bodies (plain, cmp, "plain", "mis-encoded");
+	g_byte_array_free (cmp, TRUE);
+	g_object_unref (req);
+
+	/* Plain text data, claim deflate */
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate\n");
+	req = soup_requester_request_uri (requester, uri, NULL);
+	msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+	soup_message_headers_append (msg->request_headers,
+				     "X-Test-Options", "prefer-deflate-zlib");
+	cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED);
+	check_req_bodies (plain, cmp, "plain", "compressed");
+	g_byte_array_free (cmp, TRUE);
+	g_object_unref (req);
+
+	/* Plain text data, claim deflate w/ junk */
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate, plus trailing junk\n");
+	req = soup_requester_request_uri (requester, uri, NULL);
+	msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+	soup_message_headers_append (msg->request_headers,
+				     "X-Test-Options", "prefer-deflate-zlib, trailing-junk");
+	cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED);
+	check_req_bodies (plain, cmp, "plain", "compressed w/ junk");
+	g_byte_array_free (cmp, TRUE);
+	g_object_unref (req);
+
+	/* Plain text data, claim deflate with server error */
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate, with server error\n");
+	req = soup_requester_request_uri (requester, uri, NULL);
+	msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+	soup_message_headers_append (msg->request_headers,
+				     "X-Test-Options", "force-encode, prefer-deflate-zlib");
+	cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED);
+	check_req_bodies (plain, cmp, "plain", "mis-encoded");
+	g_byte_array_free (cmp, TRUE);
+	g_object_unref (req);
+
+	/* Plain text data, claim deflate (no zlib headers)*/
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate (raw data)\n");
+	req = soup_requester_request_uri (requester, uri, NULL);
+	msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+	soup_message_headers_append (msg->request_headers,
+				     "X-Test-Options", "prefer-deflate-raw");
+	cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED);
+	check_req_bodies (plain, cmp, "plain", "compressed");
+	g_byte_array_free (cmp, TRUE);
+	g_object_unref (req);
+
+	/* Plain text data, claim deflate with server error */
+	debug_printf (1, "  GET /mbox, Accept-Encoding: deflate (raw data), with server error\n");
+	req = soup_requester_request_uri (requester, uri, NULL);
+	msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+	soup_message_headers_append (msg->request_headers,
+				     "X-Test-Options", "force-encode, prefer-deflate-raw");
+	cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED);
+	check_req_bodies (plain, cmp, "plain", "mis-encoded");
+	g_byte_array_free (cmp, TRUE);
+	g_object_unref (req);
+
+	g_byte_array_free (plain, TRUE);
+	soup_uri_free (uri);
+
+	soup_test_session_abort_unref (session);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -312,6 +550,7 @@ main (int argc, char **argv)
 	soup_uri_set_port (base_uri, soup_server_get_port (server));
 
 	do_coding_test ();
+	do_coding_req_test ();
 
 	soup_uri_free (base_uri);
 	soup_test_server_quit_unref (server);



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