[libsoup/wip/soup-uri-removal] Restore ability to send/recv `OPTIONS *` messages Since GUri does not support an invalid path of jus




commit 44504224d50b3947b5e624d5c913575f0f369b41
Author: Patrick Griffis <pgriffis igalia com>
Date:   Mon Nov 9 15:21:26 2020 -0600

    Restore ability to send/recv `OPTIONS *` messages
    Since GUri does not support an invalid path of just `*` we have to
    handle that ourselves.

 docs/reference/libsoup-3.0-sections.txt      |  1 +
 libsoup/server/soup-server-io.c              |  3 ++-
 libsoup/server/soup-server-message-private.h |  2 ++
 libsoup/server/soup-server-message.c         | 23 ++++++++++++++++++++
 libsoup/server/soup-server-message.h         |  3 +++
 libsoup/server/soup-server.c                 | 18 +++++++++++-----
 libsoup/soup-message-io.c                    |  8 ++++---
 libsoup/soup-message-private.h               |  2 ++
 libsoup/soup-message.c                       | 32 ++++++++++++++++++++++++++++
 tests/server-test.c                          | 15 ++++++++-----
 10 files changed, 93 insertions(+), 14 deletions(-)
---
diff --git a/docs/reference/libsoup-3.0-sections.txt b/docs/reference/libsoup-3.0-sections.txt
index 41df03bf..f66f50fc 100644
--- a/docs/reference/libsoup-3.0-sections.txt
+++ b/docs/reference/libsoup-3.0-sections.txt
@@ -281,6 +281,7 @@ soup_server_message_get_socket
 soup_server_message_get_local_address
 soup_server_message_get_remote_address
 soup_server_message_get_remote_host
+soup_server_message_is_options_ping
 soup_server_message_steal_connection
 <SUBSECTION Standard>
 SOUP_SERVER_MESSAGE
diff --git a/libsoup/server/soup-server-io.c b/libsoup/server/soup-server-io.c
index 3e99acd7..acc8f2ad 100644
--- a/libsoup/server/soup-server-io.c
+++ b/libsoup/server/soup-server-io.c
@@ -592,10 +592,11 @@ parse_headers (SoupServerMessage *msg,
 
        if (!strcmp (req_path, "*") && req_host) {
                /* Eg, "OPTIONS * HTTP/1.1" */
-               url = g_strdup_printf ("%s://%s/*",
+               url = g_strdup_printf ("%s://%s/",
                                       soup_socket_is_ssl (sock) ? "https" : "http",
                                       req_host);
                uri = g_uri_parse (url, SOUP_HTTP_URI_FLAGS, NULL);
+                soup_server_message_set_options_ping (msg, TRUE);
                g_free (url);
        } else if (soup_server_message_get_method (msg) == SOUP_METHOD_CONNECT) {
                /* Authority */
diff --git a/libsoup/server/soup-server-message-private.h b/libsoup/server/soup-server-message-private.h
index a4904653..55ef608c 100644
--- a/libsoup/server/soup-server-message-private.h
+++ b/libsoup/server/soup-server-message-private.h
@@ -40,6 +40,8 @@ void               soup_server_message_finished            (SoupServerMessage
 void               soup_server_message_read_request        (SoupServerMessage        *msg,
                                                             SoupMessageIOCompletionFn completion_cb,
                                                             gpointer                  user_data);
+void               soup_server_message_set_options_ping    (SoupServerMessage        *msg,
+                                                            gboolean                  is_options_ping);
 
 typedef struct _SoupServerMessageIOData SoupServerMessageIOData;
 void                     soup_server_message_io_data_free  (SoupServerMessageIOData *io);
diff --git a/libsoup/server/soup-server-message.c b/libsoup/server/soup-server-message.c
index f97912ae..5842cdd3 100644
--- a/libsoup/server/soup-server-message.c
+++ b/libsoup/server/soup-server-message.c
@@ -68,6 +68,8 @@ struct _SoupServerMessage {
         SoupMessageHeaders *response_headers;
 
         SoupServerMessageIOData *io_data;
+
+        gboolean                 options_ping;
 };
 
 struct _SoupServerMessageClass {
@@ -569,6 +571,27 @@ soup_server_message_set_method (SoupServerMessage *msg,
         msg->method = g_intern_string (method);
 }
 
+void
+soup_server_message_set_options_ping (SoupServerMessage *msg,
+                                      gboolean           is_options_ping)
+{
+        msg->options_ping = is_options_ping;
+}
+
+/**
+ * soup_server_message_is_options_ping:
+ * @msg: a #SoupServerMessage
+ *
+ * Returns if @msg represents an OPTIONS message with the path `*`.
+ */
+gboolean
+soup_server_message_is_options_ping (SoupServerMessage *msg)
+{
+        g_return_val_if_fail (SOUP_IS_SERVER_MESSAGE (msg), FALSE);
+
+        return msg->options_ping;
+}
+
 /**
  * soup_server_message_get_http_version:
  * @msg: a #SoupServerMessage
diff --git a/libsoup/server/soup-server-message.h b/libsoup/server/soup-server-message.h
index 7d29b2c2..d3f202d0 100644
--- a/libsoup/server/soup-server-message.h
+++ b/libsoup/server/soup-server-message.h
@@ -74,6 +74,9 @@ const char         *soup_server_message_get_remote_host       (SoupServerMessage
 SOUP_AVAILABLE_IN_ALL
 GIOStream          *soup_server_message_steal_connection      (SoupServerMessage *msg);
 
+SOUP_AVAILABLE_IN_ALL
+gboolean            soup_server_message_is_options_ping       (SoupServerMessage *msg);
+
 G_END_DECLS
 
 #endif /* __SOUP_SERVER_MESSAGE_H__ */
diff --git a/libsoup/server/soup-server.c b/libsoup/server/soup-server.c
index 7fa331ce..c0dd5cfb 100644
--- a/libsoup/server/soup-server.c
+++ b/libsoup/server/soup-server.c
@@ -721,15 +721,23 @@ soup_server_get_listeners (SoupServer *server)
  */
 #define NORMALIZED_PATH(path) ((path) && *(path) ? (path) : "/")
 
+static const char *
+get_msg_path (SoupServerMessage *msg)
+{
+        /* A GUri cannot hold a path of "*" so we handle that */
+        if (soup_server_message_is_options_ping (msg))
+                return "*";
+        else
+                return NORMALIZED_PATH (g_uri_get_path (soup_server_message_get_uri (msg)));
+}
+
 static SoupServerHandler *
 get_handler (SoupServer        *server,
             SoupServerMessage *msg)
 {
        SoupServerPrivate *priv = soup_server_get_instance_private (server);
-       GUri *uri;
 
-       uri = soup_server_message_get_uri (msg);
-       return soup_path_map_lookup (priv->handlers, NORMALIZED_PATH (g_uri_get_path (uri)));
+       return soup_path_map_lookup (priv->handlers, get_msg_path (msg));
 }
 
 static void
@@ -757,11 +765,11 @@ call_handler (SoupServer        *server,
 
        if (early) {
                (*handler->early_callback) (server, msg,
-                                           g_uri_get_path (uri), form_data_set,
+                                           get_msg_path (msg), form_data_set,
                                            handler->early_user_data);
        } else {
                (*handler->callback) (server, msg,
-                                     g_uri_get_path (uri), form_data_set,
+                                     get_msg_path (msg), form_data_set,
                                      handler->user_data);
        }
 
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 6976241a..7ac2667a 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -279,10 +279,12 @@ write_headers (SoupMessage          *msg,
                /* Proxy expects full URI to destination. Otherwise
                 * just the path.
                 */
-                if (!proxy)
-                        uri_string = soup_uri_get_path_and_query (uri);
-                else
+                if (proxy)
                         uri_string = g_uri_to_string (uri);
+                else if (soup_message_is_options_ping (msg))
+                        uri_string = g_strdup ("*");
+                else
+                        uri_string = soup_uri_get_path_and_query (uri);
 
                if (proxy && g_uri_get_fragment (uri)) {
                        /* Strip fragment */
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index b10928cc..f6442f99 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -136,4 +136,6 @@ void                soup_message_set_reason_phrase       (SoupMessage        *ms
 void                soup_message_set_method              (SoupMessage        *msg,
                                                           const char         *method);
 
+gboolean            soup_message_is_options_ping         (SoupMessage        *msg);
+
 #endif /* __SOUP_MESSAGE_PRIVATE_H__ */
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index 2ebea9c6..801a4609 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -90,6 +90,7 @@ typedef struct {
        SoupMessagePriority priority;
 
        gboolean is_top_level_navigation;
+        gboolean options_ping;
 } SoupMessagePrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (SoupMessage, soup_message, G_TYPE_OBJECT)
@@ -134,6 +135,7 @@ enum {
        PROP_PRIORITY,
        PROP_SITE_FOR_COOKIES,
        PROP_IS_TOP_LEVEL_NAVIGATION,
+        PROP_OPTIONS_PING,
 
        LAST_PROP
 };
@@ -219,6 +221,9 @@ soup_message_set_property (GObject *object, guint prop_id,
        case PROP_PRIORITY:
                priv->priority = g_value_get_enum (value);
                break;
+       case PROP_OPTIONS_PING:
+               priv->options_ping = g_value_get_boolean (value);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -275,6 +280,9 @@ soup_message_get_property (GObject *object, guint prop_id,
        case PROP_PRIORITY:
                g_value_set_enum (value, priv->priority);
                break;
+       case PROP_OPTIONS_PING:
+                g_value_set_boolean (value, priv->options_ping);
+                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -742,6 +750,22 @@ soup_message_class_init (SoupMessageClass *message_class)
                                   SOUP_MESSAGE_PRIORITY_NORMAL,
                                   G_PARAM_READWRITE |
                                   G_PARAM_STATIC_STRINGS));
+
+       /**
+        * SoupMessage:options-ping:
+        *
+        * The #SoupMessage is intended to be used to send
+         * `OPTIONS *` to a server and the path of
+         * #SoupMessage:uri will be ignored.
+        */
+       g_object_class_install_property (
+               object_class, PROP_OPTIONS_PING,
+               g_param_spec_boolean ("options-ping",
+                                     "Options Ping",
+                                     "The message is an OPTIONS ping",
+                                      FALSE,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_STATIC_STRINGS));
 }
 
 
@@ -2191,3 +2215,11 @@ soup_message_set_method (SoupMessage *msg,
 
         priv->method = g_intern_string (method);
 }
+
+gboolean
+soup_message_is_options_ping (SoupMessage *msg)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        return priv->options_ping;
+}
\ No newline at end of file
diff --git a/tests/server-test.c b/tests/server-test.c
index 9cc16612..90ab80a8 100644
--- a/tests/server-test.c
+++ b/tests/server-test.c
@@ -131,14 +131,15 @@ do_star_test (ServerData *sd, gconstpointer test_data)
 
        g_test_bug ("590751");
 
-        g_test_skip ("The literal path \"*\" is not a valid GUri");
-        return;
-
        session = soup_test_session_new (NULL);
         star_uri = g_uri_parse_relative (sd->base_uri, "*", SOUP_HTTP_URI_FLAGS, NULL);
 
        debug_printf (1, "  Testing with no handler\n");
-       msg = soup_message_new_from_uri ("OPTIONS", star_uri);
+       msg = g_object_new (SOUP_TYPE_MESSAGE,
+                            "method", SOUP_METHOD_OPTIONS,
+                            "uri", sd->base_uri,
+                            "options-ping", TRUE,
+                            NULL);
        soup_test_session_send_message (session, msg);
 
        soup_test_assert_message_status (msg, SOUP_STATUS_NOT_FOUND);
@@ -150,7 +151,11 @@ do_star_test (ServerData *sd, gconstpointer test_data)
        server_add_handler (sd, "*", server_star_callback, NULL, NULL);
 
        debug_printf (1, "  Testing with handler\n");
-       msg = soup_message_new_from_uri ("OPTIONS", star_uri);
+       msg = g_object_new (SOUP_TYPE_MESSAGE,
+                            "method", SOUP_METHOD_OPTIONS,
+                            "uri", sd->base_uri,
+                            "options-ping", TRUE,
+                            NULL);
        soup_test_session_send_message (session, msg);
 
        soup_test_assert_message_status (msg, SOUP_STATUS_OK);


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