SoupSession: count redirections and cancel the message after too many
authorJosé Millán Soto <jmillan@igalia.com>
Fri, 4 Jun 2010 11:46:31 +0000 (13:46 +0200)
committerDan Winship <danw@gnome.org>
Tue, 8 Jun 2010 15:19:46 +0000 (11:19 -0400)
and add a test to redirect-test

https://bugzilla.gnome.org/show_bug.cgi?id=604383

libsoup/soup-message-queue.h
libsoup/soup-session.c
libsoup/soup-status.c
libsoup/soup-status.h
tests/redirect-test.c

index b7bc5d1..d4376a7 100644 (file)
@@ -31,6 +31,8 @@ struct SoupMessageQueueItem {
        SoupURI *proxy_uri;
        SoupConnection *conn;
 
+       guint redirection_count;
+
        guint resolving_proxy_addr : 1;
        guint resolved_proxy_addr  : 1;
 
index 5143a48..1d5e6f5 100644 (file)
@@ -117,6 +117,8 @@ static void auth_manager_authenticate (SoupAuthManager *manager,
 #define SOUP_SESSION_MAX_CONNS_DEFAULT 10
 #define SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT 2
 
+#define SOUP_SESSION_MAX_REDIRECTION_COUNT 20
+
 #define SOUP_SESSION_USER_AGENT_BASE "libsoup/" PACKAGE_VERSION
 
 G_DEFINE_ABSTRACT_TYPE (SoupSession, soup_session, G_TYPE_OBJECT)
@@ -1092,7 +1094,8 @@ auth_manager_authenticate (SoupAuthManager *manager, SoupMessage *msg,
 static void
 redirect_handler (SoupMessage *msg, gpointer user_data)
 {
-       SoupSession *session = user_data;
+       SoupMessageQueueItem *item = user_data;
+       SoupSession *session = item->session;
        const char *new_loc;
        SoupURI *new_uri;
 
@@ -1100,6 +1103,12 @@ redirect_handler (SoupMessage *msg, gpointer user_data)
                                                "Location");
        g_return_if_fail (new_loc != NULL);
 
+       if (item->redirection_count >= SOUP_SESSION_MAX_REDIRECTION_COUNT) {
+               soup_session_cancel_message (session, msg, SOUP_STATUS_TOO_MANY_REDIRECTS);
+               return;
+       }
+       item->redirection_count++;
+
        if (msg->status_code == SOUP_STATUS_SEE_OTHER ||
            (msg->status_code == SOUP_STATUS_FOUND &&
             !SOUP_METHOD_IS_SAFE (msg->method)) ||
@@ -1555,7 +1564,7 @@ queue_message (SoupSession *session, SoupMessage *msg,
        if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_NO_REDIRECT)) {
                soup_message_add_header_handler (
                        msg, "got_body", "Location",
-                       G_CALLBACK (redirect_handler), session);
+                       G_CALLBACK (redirect_handler), item);
        }
 
        g_signal_emit (session, signals[REQUEST_QUEUED], 0, msg);
index 2fa309a..12473f6 100644 (file)
@@ -78,6 +78,7 @@
  * closed the connection unexpectedly
  * @SOUP_STATUS_MALFORMED: Malformed data (usually a programmer error)
  * @SOUP_STATUS_TRY_AGAIN: Used internally
+ * @SOUP_STATUS_TOO_MANY_REDIRECTS: There were too many redirections
  * @SOUP_STATUS_CONTINUE: 100 Continue (HTTP)
  * @SOUP_STATUS_SWITCHING_PROTOCOLS: 101 Switching Protocols (HTTP)
  * @SOUP_STATUS_PROCESSING: 102 Processing (WebDAV)
@@ -185,6 +186,7 @@ static const struct {
 #endif
        { SOUP_STATUS_IO_ERROR,                   "Connection terminated unexpectedly" },
        { SOUP_STATUS_MALFORMED,                  "Message Corrupt" },
+       { SOUP_STATUS_TOO_MANY_REDIRECTS,         "Too many redirects" },
 
        /* Informational */
        { SOUP_STATUS_CONTINUE,                   "Continue" },
index 66e9f1c..0d8b74f 100644 (file)
@@ -32,6 +32,7 @@ typedef enum {
        SOUP_STATUS_IO_ERROR,
        SOUP_STATUS_MALFORMED,
        SOUP_STATUS_TRY_AGAIN,
+       SOUP_STATUS_TOO_MANY_REDIRECTS,
 
        /* HTTP Status Codes */
        SOUP_STATUS_CONTINUE                        = 100,
index cd6f1a5..24aefc4 100644 (file)
@@ -18,6 +18,7 @@ typedef struct {
        const char *method;
        const char *path;
        guint status_code;
+       gboolean repeat;
 } TestRequest;
 
 static struct {
@@ -107,7 +108,10 @@ static struct {
 
        /* Test behavior with irrecoverably-bad Location header */
        { { { "GET", "/bad-no-host", 302 },
-           { NULL } }, SOUP_STATUS_MALFORMED }
+           { NULL } }, SOUP_STATUS_MALFORMED },
+
+       { { { "GET", "/bad-recursive", 302, TRUE },
+           { NULL } }, SOUP_STATUS_TOO_MANY_REDIRECTS }
 };
 static const int n_tests = G_N_ELEMENTS (tests);
 
@@ -142,7 +146,7 @@ restarted (SoupMessage *msg, gpointer user_data)
 
        debug_printf (2, "    %s %s\n", msg->method, uri->path);
 
-       if ((*req)->method)
+       if ((*req)->method && !(*req)->repeat)
                (*req)++;
 
        if (!(*req)->method) {
@@ -234,6 +238,11 @@ server_callback (SoupServer *server, SoupMessage *msg,
                        soup_message_headers_replace (msg->response_headers,
                                                      "Location",
                                                      "/bad with spaces");
+               } else if (!strcmp (path, "/bad-recursive")) {
+                       soup_message_set_status (msg, SOUP_STATUS_FOUND);
+                       soup_message_headers_replace (msg->response_headers,
+                                                     "Location",
+                                                     "/bad-recursive");
                } else if (!strcmp (path, "/bad-no-host")) {
                        soup_message_set_status (msg, SOUP_STATUS_FOUND);
                        soup_message_headers_replace (msg->response_headers,