[libsoup] Add soup_message_disable_feature()



commit 005bf1a75397d66028454e58e4aa1d95ac88569d
Author: Dan Winship <danw gnome org>
Date:   Sun Aug 2 11:35:01 2009 -0400

    Add soup_message_disable_feature()
    
    This allows you to disable specific SoupSessionFeatures for particular
    messages.
    
    Also update tests/sniffing-test to test it out.
    
    http://bugzilla.gnome.org/show_bug.cgi?id=574773

 libsoup/soup-message-private.h |    4 ++
 libsoup/soup-message.c         |   52 ++++++++++++++++++++++++++++++++++
 libsoup/soup-message.h         |    3 ++
 libsoup/soup-session-async.c   |    3 +-
 libsoup/soup-session-feature.c |   10 ++++++
 libsoup/soup-session-sync.c    |    3 +-
 tests/sniffing-test.c          |   61 ++++++++++++++++++++++++++++++++++------
 7 files changed, 125 insertions(+), 11 deletions(-)
---
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index 5c88cbc..765ee3c 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -39,6 +39,8 @@ typedef struct {
 	SoupAddress       *addr;
 
 	SoupAuth          *auth, *proxy_auth;
+
+	GSList            *disabled_features;
 } SoupMessagePrivate;
 #define SOUP_MESSAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_MESSAGE, SoupMessagePrivate))
 
@@ -94,4 +96,6 @@ void                soup_message_io_pause       (SoupMessage          *msg);
 void                soup_message_io_unpause     (SoupMessage          *msg);
 gboolean            soup_message_io_in_progress (SoupMessage          *msg);
 
+gboolean soup_message_disables_feature (SoupMessage *msg,
+					gpointer     feature);
 #endif /* SOUP_MESSAGE_PRIVATE_H */
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index f614946..1f0c8ac 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -166,6 +166,8 @@ finalize (GObject *object)
 	if (priv->proxy_auth)
 		g_object_unref (priv->proxy_auth);
 
+	g_slist_free (priv->disabled_features);
+
 	soup_message_body_free (msg->request_body);
 	soup_message_headers_free (msg->request_headers);
 	soup_message_body_free (msg->response_body);
@@ -1601,3 +1603,53 @@ soup_message_set_chunk_allocator (SoupMessage *msg,
 	priv->chunk_allocator_data    = user_data;
 	priv->chunk_allocator_dnotify = destroy_notify;
 }
+
+/**
+ * soup_message_disable_feature:
+ * @msg: a #SoupMessage
+ * @feature_type: the #GType of a #SoupSessionFeature
+ *
+ * This disables the actions of #SoupSessionFeature<!-- -->s with the
+ * given @feature_type (or a subclass of that type) on @msg, so that
+ * @msg is processed as though the feature(s) hadn't been added to the
+ * session. Eg, passing #SOUP_TYPE_PROXY_RESOLVER for @feature_type
+ * will disable proxy handling and cause @msg to be sent directly to
+ * the indicated origin server, regardless of system proxy
+ * configuration.
+ *
+ * You must call this before queueing @msg on a session; calling it on
+ * a message that has already been queued is undefined. In particular,
+ * you cannot call this on a message that is being requeued after a
+ * redirect or authentication.
+ *
+ * Since: 2.28
+ **/
+void
+soup_message_disable_feature (SoupMessage *msg, GType feature_type)
+{
+	SoupMessagePrivate *priv;
+
+	g_return_if_fail (SOUP_IS_MESSAGE (msg));
+
+	priv = SOUP_MESSAGE_GET_PRIVATE (msg);
+
+	priv->disabled_features = g_slist_prepend (priv->disabled_features,
+						   GSIZE_TO_POINTER (feature_type));
+}
+
+gboolean
+soup_message_disables_feature (SoupMessage *msg, gpointer feature)
+{
+	SoupMessagePrivate *priv;
+	GSList *f;
+
+	g_return_val_if_fail (SOUP_IS_MESSAGE (msg), FALSE);
+
+	priv = SOUP_MESSAGE_GET_PRIVATE (msg);
+
+	for (f = priv->disabled_features; f; f = f->next) {
+		if (G_TYPE_CHECK_INSTANCE_TYPE (feature, (GType) GPOINTER_TO_SIZE (f->data)))
+			return TRUE;
+	}
+	return FALSE;
+}
diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h
index b940ac6..4bbcb1b 100644
--- a/libsoup/soup-message.h
+++ b/libsoup/soup-message.h
@@ -146,6 +146,9 @@ void           soup_message_set_chunk_allocator (SoupMessage       *msg,
 						 gpointer           user_data,
 						 GDestroyNotify     destroy_notify);
 
+void           soup_message_disable_feature     (SoupMessage       *msg,
+						 GType              feature_type);
+
 void soup_message_wrote_informational (SoupMessage *msg);
 void soup_message_wrote_headers       (SoupMessage *msg);
 void soup_message_wrote_chunk         (SoupMessage *msg);
diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c
index f505710..a4e6017 100644
--- a/libsoup/soup-session-async.c
+++ b/libsoup/soup-session-async.c
@@ -317,7 +317,8 @@ run_queue (SoupSessionAsync *sa)
 		    soup_message_io_in_progress (msg))
 			continue;
 
-		if (proxy_resolver && !item->resolved_proxy_addr) {
+		if (proxy_resolver && !item->resolved_proxy_addr &&
+		    !soup_message_disables_feature (item->msg, proxy_resolver)) {
 			resolve_proxy_addr (item, proxy_resolver);
 			continue;
 		}
diff --git a/libsoup/soup-session-feature.c b/libsoup/soup-session-feature.c
index 3f1ff77..f5d1239 100644
--- a/libsoup/soup-session-feature.c
+++ b/libsoup/soup-session-feature.c
@@ -10,6 +10,7 @@
 #endif
 
 #include "soup-session-feature.h"
+#include "soup-message-private.h"
 
 /**
  * SECTION:soup-session-feature
@@ -88,6 +89,9 @@ weak_notify_unref (gpointer feature, GObject *ex_object)
 static void
 request_queued (SoupSession *session, SoupMessage *msg, gpointer feature)
 {
+	if (soup_message_disables_feature (msg, feature))
+		return;
+
 	SOUP_SESSION_FEATURE_GET_CLASS (feature)->
 		request_queued (feature, session, msg);
 }
@@ -96,6 +100,9 @@ static void
 request_started (SoupSession *session, SoupMessage *msg,
 		 SoupSocket *socket, gpointer feature)
 {
+	if (soup_message_disables_feature (msg, feature))
+		return;
+
 	SOUP_SESSION_FEATURE_GET_CLASS (feature)->
 		request_started (feature, session, msg, socket);
 }
@@ -103,6 +110,9 @@ request_started (SoupSession *session, SoupMessage *msg,
 static void
 request_unqueued (SoupSession *session, SoupMessage *msg, gpointer feature)
 {
+	if (soup_message_disables_feature (msg, feature))
+		return;
+
 	SOUP_SESSION_FEATURE_GET_CLASS (feature)->
 		request_unqueued (feature, session, msg);
 }
diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c
index 8c2e56b..1c1c7dc 100644
--- a/libsoup/soup-session-sync.c
+++ b/libsoup/soup-session-sync.c
@@ -170,7 +170,8 @@ wait_for_connection (SoupMessageQueueItem *item)
 	guint status;
 
 	proxy_resolver = soup_session_get_proxy_resolver (session);
-	if (proxy_resolver && !item->resolved_proxy_addr) {
+	if (proxy_resolver && !item->resolved_proxy_addr &&
+	    !soup_message_disables_feature (item->msg, proxy_resolver)) {
 		status = soup_proxy_uri_resolver_get_proxy_uri_sync (
 			proxy_resolver, soup_message_get_uri (msg),
 			item->cancellable, &item->proxy_uri);
diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c
index a5c9587..561d2ee 100644
--- a/tests/sniffing-test.c
+++ b/tests/sniffing-test.c
@@ -343,29 +343,62 @@ do_signals_test (gboolean should_content_sniff,
 }
 
 static void
-sniffing_content_sniffed (SoupMessage *msg, char *content_type, GHashTable *params, gpointer data)
+sniffing_content_sniffed (SoupMessage *msg, const char *content_type,
+			  GHashTable *params, gpointer data)
 {
-	char *expected_type = (char*)data;
+	char **sniffed_type = (char **)data;
 
-	if (strcmp (content_type, expected_type)) {
+	*sniffed_type = g_strdup (content_type);
+}
+
+static void
+test_sniffing (const char *path, const char *expected_type)
+{
+	SoupURI *uri = soup_uri_new_with_base (base_uri, path);
+	SoupMessage *msg = soup_message_new_from_uri ("GET", uri);
+	GMainLoop *loop = g_main_loop_new (NULL, TRUE);
+	char *sniffed_type = NULL;
+
+	debug_printf (1, "test_sniffing(\"%s\", \"%s\")\n", path, expected_type);
+
+	g_signal_connect (msg, "content-sniffed",
+			  G_CALLBACK (sniffing_content_sniffed), &sniffed_type);
+
+	g_object_ref (msg);
+
+	soup_session_queue_message (session, msg, finished, loop);
+
+	g_main_loop_run (loop);
+
+	if (!sniffed_type) {
+		debug_printf (1, "  message was not sniffed!\n");
+		errors++;
+	} else if (strcmp (sniffed_type, expected_type) != 0) {
 		debug_printf (1, "  sniffing failed! expected %s, got %s\n",
-			      expected_type, content_type);
+			      expected_type, sniffed_type);
 		errors++;
 	}
+	g_free (sniffed_type);
+
+	soup_uri_free (uri);
+	g_object_unref (msg);
+	g_main_loop_unref (loop);
 }
 
 static void
-test_sniffing (const char *path, const char *expected_type)
+test_disabled (const char *path)
 {
 	SoupURI *uri = soup_uri_new_with_base (base_uri, path);
 	SoupMessage *msg = soup_message_new_from_uri ("GET", uri);
 	GMainLoop *loop = g_main_loop_new (NULL, TRUE);
+	char *sniffed_type = NULL;
 
-	debug_printf (1, "test_sniffing(\"%s\", \"%s\")\n", path, expected_type);
+	soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER);
 
-	g_object_connect (msg,
-			  "signal::content_sniffed", sniffing_content_sniffed, expected_type,
-			  NULL);
+	debug_printf (1, "test_disabled(\"%s\")\n", path);
+
+	g_signal_connect (msg, "content-sniffed",
+			  G_CALLBACK (sniffing_content_sniffed), &sniffed_type);
 
 	g_object_ref (msg);
 
@@ -373,6 +406,12 @@ test_sniffing (const char *path, const char *expected_type)
 
 	g_main_loop_run (loop);
 
+	if (sniffed_type) {
+		debug_printf (1, "  message was sniffed!\n");
+		errors++;
+		g_free (sniffed_type);
+	}
+
 	soup_uri_free (uri);
 	g_object_unref (msg);
 	g_main_loop_unref (loop);
@@ -474,6 +513,10 @@ main (int argc, char **argv)
 
 	test_sniffing ("/multiple_headers/home.gif", "image/gif");
 
+	/* Test that disabling the sniffer works correctly */
+
+	test_disabled ("/text_or_binary/home.gif");
+
 	soup_uri_free (base_uri);
 
 	test_cleanup ();



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