summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Griffis <pgriffis@igalia.com>2020-11-09 15:21:26 -0600
committerPatrick Griffis <tingping@tingping.se>2020-11-14 19:07:24 +0000
commitebc6e9569dc2bc9c226762ce89fd35950f8ad085 (patch)
tree14c61a8b593919927c1141978a9befefa49f8764
parent737eef099ca1e34d18245c54b6ed3ba54faf1f9c (diff)
downloadlibsoup-ebc6e9569dc2bc9c226762ce89fd35950f8ad085.tar.gz
Restore ability to send/recv `OPTIONS *` messages
Since GUri does not support an invalid path of just `*` we have to handle that ourselves.
-rw-r--r--docs/reference/libsoup-3.0-sections.txt1
-rw-r--r--libsoup/server/soup-server-io.c3
-rw-r--r--libsoup/server/soup-server-message-private.h2
-rw-r--r--libsoup/server/soup-server-message.c25
-rw-r--r--libsoup/server/soup-server-message.h3
-rw-r--r--libsoup/server/soup-server.c18
-rw-r--r--libsoup/soup-message-io.c8
-rw-r--r--libsoup/soup-message-private.h2
-rw-r--r--libsoup/soup-message.c32
-rw-r--r--tests/server-test.c18
10 files changed, 95 insertions, 17 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 04baff66..03b68724 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,29 @@ 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
+ *
+ * Gets if @msg represents an OPTIONS message with the path `*`.
+ *
+ * Returns: %TRUE if is an OPTIONS ping
+ */
+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 bbc10627..c49127e1 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 dfc57c11..5bee9dc1 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 769d6da7..a4d1923f 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 55716c98..ef16f8e6 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));
}
@@ -2199,3 +2223,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..36edb5a0 100644
--- a/tests/server-test.c
+++ b/tests/server-test.c
@@ -126,19 +126,18 @@ do_star_test (ServerData *sd, gconstpointer test_data)
{
SoupSession *session;
SoupMessage *msg;
- GUri *star_uri;
const char *handled_by;
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 +149,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);
@@ -160,7 +163,6 @@ do_star_test (ServerData *sd, gconstpointer test_data)
g_object_unref (msg);
soup_test_session_abort_unref (session);
- g_uri_unref (star_uri);
}
static void