[libsoup/carlosgc/websocket-connection-error] WebSockets: do not report connection errors as handshake failures




commit 046aac0bbc6bf9745e6cf970d2507c1a4342071f
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Wed Feb 10 14:53:12 2021 +0100

    WebSockets: do not report connection errors as handshake failures
    
    We are assuming that when not switching protocols after a request is
    because the server didn't accept the handshake, but we can fail even
    earlier if there's a connection error. In libsoup 2 we could check if
    it was a connection error by checking the message status was
    SOUP_STATUS_CANT_CONNECT or SOUP_STATUS_CANT_CONNECT_PROXY. Now that we
    no longer use the message status for transport errors, we should make
    soup_session_websocket_connect_async() fail with the connection error.

 libsoup/soup-session.c | 12 +++++++++---
 tests/websocket-test.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 3 deletions(-)
---
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 4509993a..baecb245 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -3729,14 +3729,20 @@ static void
 websocket_connect_async_complete (SoupSession *session, SoupMessage *msg, gpointer user_data)
 {
        GTask *task = user_data;
+       SoupMessageQueueItem *item = g_task_get_task_data (task);
 
        /* Disconnect websocket_connect_async_stop() handler. */
        g_signal_handlers_disconnect_matched (msg, G_SIGNAL_MATCH_DATA,
                                              0, 0, NULL, NULL, task);
 
-       g_task_return_new_error (task,
-                                SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET,
-                                "%s", _("The server did not accept the WebSocket handshake."));
+       if (item->error) {
+               g_task_return_error (task, g_error_copy (item->error));
+       } else {
+               g_task_return_new_error (task,
+                                        SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET,
+                                        "%s", _("The server did not accept the WebSocket handshake."));
+       }
+
        g_object_unref (task);
 }
 
diff --git a/tests/websocket-test.c b/tests/websocket-test.c
index 714f77fb..5c8a83a4 100644
--- a/tests/websocket-test.c
+++ b/tests/websocket-test.c
@@ -1986,6 +1986,36 @@ test_cookies_in_response (Test *test,
         soup_cookie_free (cookie);
 }
 
+static void
+test_connection_error_cb (GObject      *object,
+                         GAsyncResult *result,
+                         gpointer      user_data)
+{
+       GError **error = user_data;
+
+       g_assert_null (soup_session_websocket_connect_finish (SOUP_SESSION (object), result, error));
+}
+
+static void
+test_connection_error (void)
+{
+       SoupSession *session;
+       SoupMessage *msg;
+       GError *error = NULL;
+
+       session = soup_test_session_new (NULL);
+
+       msg = soup_message_new ("GET", "ws://127.0.0.1:1234/unix");
+       soup_session_websocket_connect_async (session, msg, NULL, NULL, G_PRIORITY_DEFAULT,
+                                             NULL, test_connection_error_cb, &error);
+       WAIT_UNTIL (error != NULL);
+       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED);
+
+       g_error_free (error);
+       g_object_unref (msg);
+       soup_test_session_abort_unref (session);
+}
+
 int
 main (int argc,
       char *argv[])
@@ -2219,6 +2249,8 @@ main (int argc,
                     test_cookies_in_response,
                     teardown_soup_connection);
 
+       g_test_add_func ("/websocket/soup/connection-error", test_connection_error);
+
        ret = g_test_run ();
 
        test_cleanup ();


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