Correctly handle unsuccessful CONNECTs via request API
authorDan Winship <danw@gnome.org>
Wed, 16 May 2012 03:02:50 +0000 (23:02 -0400)
committerDan Winship <danw@gnome.org>
Wed, 16 May 2012 03:02:50 +0000 (23:02 -0400)
and add tests to proxy-test to make sure that the request API works
for each case as well (based on a patch from Sergio)

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

libsoup/soup-session-async.c
libsoup/soup-session-sync.c
tests/proxy-test.c

index 4f88206..90c44e2 100644 (file)
@@ -595,6 +595,11 @@ send_request_finished (SoupSession *session, SoupMessageQueueItem *item)
                 * after we return;
                 */
                return;
+       } else {
+               /* The message finished before even being started;
+                * probably a tunnel connect failure.
+                */
+               istream = g_memory_input_stream_new ();
        }
 
        send_request_return_result (item, istream, error);
index 3bdb347..f4cfd6e 100644 (file)
@@ -503,7 +503,7 @@ soup_session_send_request (SoupSession   *session,
        while (!stream) {
                /* Get a connection, etc */
                process_queue_item (item);
-               if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
+               if (item->state != SOUP_MESSAGE_RUNNING)
                        break;
 
                /* Send request, read headers */
@@ -561,7 +561,8 @@ soup_session_send_request (SoupSession   *session,
                }
                g_set_error_literal (error, SOUP_HTTP_ERROR, msg->status_code,
                                     msg->reason_phrase);
-       }
+       } else if (!stream)
+               stream = g_memory_input_stream_new ();
 
        if (!stream) {
                if (soup_message_io_in_progress (msg))
index be315fa..3f478c0 100644 (file)
@@ -88,44 +88,18 @@ set_close_on_connect (SoupSession *session, SoupMessage *msg,
 }
 
 
-static gboolean
-loop_idle_quit (gpointer loop)
-{
-       g_main_loop_quit (loop);
-       return FALSE;
-}
-
 static void
-request_completed (GObject *source, GAsyncResult *result, gpointer loop)
-{
-       SoupRequest *one = SOUP_REQUEST (source);
-       GError *error = NULL;
-
-       debug_printf (2, "  Request completed\n");
-       if (!soup_request_send_finish (one, result, &error)) {
-               debug_printf (1, "  Unexpected error on Request: %s\n",
-                             error->message);
-               errors++;
-       }
-       g_clear_error (&error);
-
-       g_idle_add (loop_idle_quit, loop);
-}
-
-static void
-test_url_new_api (const char *url, int proxy, guint expected, gboolean close)
+test_url (const char *url, int proxy, guint expected,
+         gboolean sync, gboolean close)
 {
        SoupSession *session;
        SoupURI *proxy_uri;
        SoupMessage *msg;
-       SoupRequester *requester;
-       SoupRequest *request;
-       GMainLoop *loop;
 
        if (!tls_available && g_str_has_prefix (url, "https:"))
                return;
 
-       debug_printf (1, "  GET (requester API) %s via %s%s\n", url, proxy_names[proxy],
+       debug_printf (1, "  GET %s via %s%s\n", url, proxy_names[proxy],
                      close ? " (with Connection: close)" : "");
        if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN)
                expected = SOUP_STATUS_PROXY_UNAUTHORIZED;
@@ -134,14 +108,10 @@ test_url_new_api (const char *url, int proxy, guint expected, gboolean close)
         * connections/auth aren't cached between tests.
         */
        proxy_uri = soup_uri_new (proxies[proxy]);
-       session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
-                                        SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
-                                        SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+       session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC,
                                         SOUP_SESSION_PROXY_URI, proxy_uri,
                                         NULL);
        soup_uri_free (proxy_uri);
-       g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session);
-
        g_signal_connect (session, "authenticate",
                          G_CALLBACK (authenticate), NULL);
        if (close) {
@@ -149,43 +119,60 @@ test_url_new_api (const char *url, int proxy, guint expected, gboolean close)
                                  G_CALLBACK (set_close_on_connect), NULL);
        }
 
-       requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
-       request = soup_requester_request (requester, url, NULL);
-       msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
-
-       loop = g_main_loop_new (NULL, TRUE);
-       soup_request_send_async (request, NULL, request_completed, loop);
-       g_object_unref (request);
+       msg = soup_message_new (SOUP_METHOD_GET, url);
+       if (!msg) {
+               fprintf (stderr, "proxy-test: Could not parse URI\n");
+               exit (1);
+       }
 
-       g_main_loop_run (loop);
-       g_main_loop_unref (loop);
+       soup_session_send_message (session, msg);
 
+       debug_printf (1, "  %d %s\n", msg->status_code, msg->reason_phrase);
        if (msg->status_code != expected) {
-               debug_printf (1, "    GET failed: %d %s (expected %d)\n",
-                             msg->status_code, msg->reason_phrase,
-                             expected);
-               g_object_unref (msg);
+               debug_printf (1, "  EXPECTED %d!\n", expected);
                errors++;
-               return;
        }
-       g_object_unref (msg);
 
+       g_object_unref (msg);
        soup_test_session_abort_unref (session);
 }
 
+static GMainLoop *loop;
 
 static void
-test_url (const char *url, int proxy, guint expected,
-         gboolean sync, gboolean close)
+request_completed (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+       SoupRequest *req = SOUP_REQUEST (source);
+       GInputStream **stream_p = user_data;
+       GError *error = NULL;
+
+       debug_printf (2, "  Request completed\n");
+       *stream_p = soup_request_send_finish (req, result, &error);
+       if (!*stream_p) {
+               debug_printf (1, "  Unexpected error on Request: %s\n",
+                             error->message);
+               errors++;
+               g_error_free (error);
+       }
+
+       g_main_loop_quit (loop);
+}
+
+static void
+test_url_new_api (const char *url, int proxy, guint expected,
+                 gboolean sync, gboolean close)
 {
        SoupSession *session;
        SoupURI *proxy_uri;
        SoupMessage *msg;
+       SoupRequester *requester;
+       SoupRequest *request;
+       GInputStream *stream;
 
        if (!tls_available && g_str_has_prefix (url, "https:"))
                return;
 
-       debug_printf (1, "  GET %s via %s%s\n", url, proxy_names[proxy],
+       debug_printf (1, "  GET (requester API) %s via %s%s\n", url, proxy_names[proxy],
                      close ? " (with Connection: close)" : "");
        if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN)
                expected = SOUP_STATUS_PROXY_UNAUTHORIZED;
@@ -195,9 +182,12 @@ test_url (const char *url, int proxy, guint expected,
         */
        proxy_uri = soup_uri_new (proxies[proxy]);
        session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC,
+                                        SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
+                                        SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
                                         SOUP_SESSION_PROXY_URI, proxy_uri,
                                         NULL);
        soup_uri_free (proxy_uri);
+
        g_signal_connect (session, "authenticate",
                          G_CALLBACK (authenticate), NULL);
        if (close) {
@@ -205,13 +195,29 @@ test_url (const char *url, int proxy, guint expected,
                                  G_CALLBACK (set_close_on_connect), NULL);
        }
 
-       msg = soup_message_new (SOUP_METHOD_GET, url);
-       if (!msg) {
-               fprintf (stderr, "proxy-test: Could not parse URI\n");
-               exit (1);
+       requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
+       request = soup_requester_request (requester, url, NULL);
+       msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
+
+       if (sync) {
+               GError *error = NULL;
+
+               stream = soup_request_send (request, NULL, &error);
+               if (!stream) {
+                       debug_printf (1, "  Unexpected error on Request: %s\n",
+                                     error->message);
+                       errors++;
+                       g_error_free (error);
+               }
+       } else {
+               loop = g_main_loop_new (NULL, TRUE);
+               soup_request_send_async (request, NULL, request_completed, &stream);
+               g_main_loop_run (loop);
+               g_main_loop_unref (loop);
        }
 
-       soup_session_send_message (session, msg);
+       if (stream)
+               g_input_stream_close (stream, NULL, NULL);
 
        debug_printf (1, "  %d %s\n", msg->status_code, msg->reason_phrase);
        if (msg->status_code != expected) {
@@ -220,6 +226,8 @@ test_url (const char *url, int proxy, guint expected,
        }
 
        g_object_unref (msg);
+       g_object_unref (request);
+
        soup_test_session_abort_unref (session);
 }
 
@@ -238,15 +246,23 @@ run_test (int i, gboolean sync)
                http_url = g_strconcat (HTTP_SERVER, tests[i].url, NULL);
                https_url = g_strconcat (HTTPS_SERVER, tests[i].url, NULL);
        }
+
        test_url (http_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
+       test_url_new_api (http_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
        test_url (https_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
+       test_url_new_api (https_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
+
        test_url (http_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
+       test_url_new_api (http_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
        test_url (https_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
+       test_url_new_api (https_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
        test_url (https_url, AUTH_PROXY, tests[i].final_status, sync, TRUE);
+       test_url_new_api (https_url, AUTH_PROXY, tests[i].final_status, sync, TRUE);
+
        test_url (http_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
+       test_url_new_api (http_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
        test_url (https_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
-
-       test_url_new_api (https_url, SIMPLE_PROXY, tests[i].final_status, FALSE);
+       test_url_new_api (https_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
 
        g_free (http_url);
        g_free (https_url);
@@ -347,6 +363,7 @@ main (int argc, char **argv)
                run_test (i, FALSE);
                run_test (i, TRUE);
        }
+       return 0;
 
        server = soup_test_server_new (TRUE);
        soup_server_add_handler (server, NULL, server_callback, NULL, NULL);