[libsoup] soup-session: fix some http-aliases/https-aliases problems
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup] soup-session: fix some http-aliases/https-aliases problems
- Date: Thu, 1 Dec 2011 10:18:31 +0000 (UTC)
commit c524540f1eb7c1d68597227ab677b47345bc54b5
Author: Dan Winship <danw gnome org>
Date: Wed Nov 30 13:34:43 2011 +0100
soup-session: fix some http-aliases/https-aliases problems
and add a test to misc-test
libsoup/soup-session.c | 78 ++++++++++++++++++++++++++++++-----
libsoup/soup-uri.c | 4 --
tests/misc-test.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 171 insertions(+), 17 deletions(-)
---
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 94b50a2..3babab4 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -73,6 +73,8 @@ typedef struct {
GSource *keep_alive_src;
SoupSession *session;
} SoupSessionHost;
+static guint soup_host_uri_hash (gconstpointer key);
+gboolean soup_host_uri_equal (gconstpointer v1, gconstpointer v2);
typedef struct {
GTlsDatabase *tlsdb;
@@ -88,7 +90,7 @@ typedef struct {
GSList *features;
GHashTable *features_cache;
- GHashTable *hosts; /* char* -> SoupSessionHost */
+ GHashTable *http_hosts, *https_hosts; /* char* -> SoupSessionHost */
GHashTable *conns; /* SoupConnection -> SoupSessionHost */
guint num_conns;
guint max_conns, max_conns_per_host;
@@ -186,9 +188,12 @@ soup_session_init (SoupSession *session)
priv->queue = soup_message_queue_new (session);
g_mutex_init (&priv->host_lock);
- priv->hosts = g_hash_table_new_full (soup_uri_host_hash,
- soup_uri_host_equal,
- NULL, (GDestroyNotify)free_host);
+ priv->http_hosts = g_hash_table_new_full (soup_host_uri_hash,
+ soup_host_uri_equal,
+ NULL, (GDestroyNotify)free_host);
+ priv->https_hosts = g_hash_table_new_full (soup_host_uri_hash,
+ soup_host_uri_equal,
+ NULL, (GDestroyNotify)free_host);
priv->conns = g_hash_table_new (NULL, NULL);
priv->max_conns = SOUP_SESSION_MAX_CONNS_DEFAULT;
@@ -241,7 +246,8 @@ finalize (GObject *object)
soup_message_queue_destroy (priv->queue);
g_mutex_clear (&priv->host_lock);
- g_hash_table_destroy (priv->hosts);
+ g_hash_table_destroy (priv->http_hosts);
+ g_hash_table_destroy (priv->https_hosts);
g_hash_table_destroy (priv->conns);
g_free (priv->user_agent);
@@ -1048,12 +1054,18 @@ load_ssl_ca_file (SoupSessionPrivate *priv)
static void
set_aliases (char ***variable, char **value)
{
- int len = g_strv_length (value), i;
+ int len, i;
if (*variable)
g_free (*variable);
- *variable = g_new (char *, len);
+ if (!value) {
+ *variable = NULL;
+ return;
+ }
+
+ len = g_strv_length (value);
+ *variable = g_new (char *, len + 1);
for (i = 0; i < len; i++)
(*variable)[i] = (char *)g_intern_string (value[i]);
(*variable)[i] = NULL;
@@ -1358,6 +1370,32 @@ soup_session_get_async_context (SoupSession *session)
/* Hosts */
+static guint
+soup_host_uri_hash (gconstpointer key)
+{
+ const SoupURI *uri = key;
+
+ g_return_val_if_fail (uri != NULL && uri->host != NULL, 0);
+
+ return uri->port + soup_str_case_hash (uri->host);
+}
+
+gboolean
+soup_host_uri_equal (gconstpointer v1, gconstpointer v2)
+{
+ const SoupURI *one = v1;
+ const SoupURI *two = v2;
+
+ g_return_val_if_fail (one != NULL && two != NULL, one == two);
+ g_return_val_if_fail (one->host != NULL && two->host != NULL, one->host == two->host);
+
+ if (one->port != two->port)
+ return FALSE;
+
+ return g_ascii_strcasecmp (one->host, two->host) == 0;
+}
+
+
static SoupSessionHost *
soup_session_host_new (SoupSession *session, SoupURI *uri)
{
@@ -1365,6 +1403,16 @@ soup_session_host_new (SoupSession *session, SoupURI *uri)
host = g_slice_new0 (SoupSessionHost);
host->uri = soup_uri_copy_host (uri);
+ if (host->uri->scheme != SOUP_URI_SCHEME_HTTP &&
+ host->uri->scheme != SOUP_URI_SCHEME_HTTPS) {
+ SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
+
+ if (uri_is_https (priv, host->uri))
+ host->uri->scheme = SOUP_URI_SCHEME_HTTPS;
+ else
+ host->uri->scheme = SOUP_URI_SCHEME_HTTP;
+ }
+
host->addr = soup_address_new (host->uri->host, host->uri->port);
host->keep_alive_src = NULL;
host->session = session;
@@ -1379,12 +1427,19 @@ get_host_for_uri (SoupSession *session, SoupURI *uri)
SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
SoupSessionHost *host;
- host = g_hash_table_lookup (priv->hosts, uri);
+ if (uri_is_https (priv, uri))
+ host = g_hash_table_lookup (priv->https_hosts, uri);
+ else
+ host = g_hash_table_lookup (priv->http_hosts, uri);
if (host)
return host;
host = soup_session_host_new (session, uri);
- g_hash_table_insert (priv->hosts, host->uri, host);
+
+ if (uri_is_https (priv, uri))
+ g_hash_table_insert (priv->https_hosts, host->uri, host);
+ else
+ g_hash_table_insert (priv->http_hosts, host->uri, host);
return host;
}
@@ -1684,7 +1739,10 @@ free_unused_host (gpointer user_data)
/* This will free the host in addition to removing it from the
* hash table
*/
- g_hash_table_remove (priv->hosts, host->uri);
+ if (host->uri->scheme == SOUP_URI_SCHEME_HTTPS)
+ g_hash_table_remove (priv->https_hosts, host->uri);
+ else
+ g_hash_table_remove (priv->http_hosts, host->uri);
g_mutex_unlock (&priv->host_lock);
return FALSE;
diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c
index 9170feb..cb7c5ce 100644
--- a/libsoup/soup-uri.c
+++ b/libsoup/soup-uri.c
@@ -742,10 +742,6 @@ soup_uri_normalize (const char *part, const char *unescape_extra)
gboolean
soup_uri_uses_default_port (SoupURI *uri)
{
- g_return_val_if_fail (uri->scheme == SOUP_URI_SCHEME_HTTP ||
- uri->scheme == SOUP_URI_SCHEME_HTTPS ||
- uri->scheme == SOUP_URI_SCHEME_FTP, FALSE);
-
return uri->port == soup_scheme_default_port (uri->scheme);
}
diff --git a/tests/misc-test.c b/tests/misc-test.c
index b1bc2e7..332e938 100644
--- a/tests/misc-test.c
+++ b/tests/misc-test.c
@@ -18,8 +18,8 @@
#include "test-utils.h"
-SoupServer *server;
-SoupURI *base_uri;
+SoupServer *server, *ssl_server;
+SoupURI *base_uri, *ssl_base_uri;
GMutex server_mutex;
static gboolean
@@ -117,6 +117,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
SoupClientContext *context, gpointer data)
{
SoupURI *uri = soup_message_get_uri (msg);
+ const char *server_protocol = data;
/* The way this gets used in the tests, we don't actually
* need to hold it through the whole function, so it's simpler
@@ -145,6 +146,34 @@ server_callback (SoupServer *server, SoupMessage *msg,
return;
}
+ if (!strcmp (path, "/alias-redirect")) {
+ SoupURI *redirect_uri;
+ char *redirect_string;
+ const char *redirect_protocol;
+
+ redirect_protocol = soup_message_headers_get_one (msg->request_headers, "X-Redirect-Protocol");
+
+ redirect_uri = soup_uri_copy (uri);
+ soup_uri_set_scheme (redirect_uri, "foo");
+ if (!g_strcmp0 (redirect_protocol, "https"))
+ soup_uri_set_port (redirect_uri, ssl_base_uri->port);
+ else
+ soup_uri_set_port (redirect_uri, base_uri->port);
+ soup_uri_set_path (redirect_uri, "/alias-redirected");
+ redirect_string = soup_uri_to_string (redirect_uri, FALSE);
+
+ soup_message_set_redirect (msg, SOUP_STATUS_FOUND, redirect_string);
+ g_free (redirect_string);
+ soup_uri_free (redirect_uri);
+ return;
+ } else if (!strcmp (path, "/alias-redirected")) {
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ soup_message_headers_append (msg->response_headers,
+ "X-Redirected-Protocol",
+ server_protocol);
+ return;
+ }
+
if (g_str_has_prefix (path, "/content-length/")) {
gboolean too_long = strcmp (path, "/content-length/long") == 0;
gboolean no_close = strcmp (path, "/content-length/noclose") == 0;
@@ -1011,6 +1040,69 @@ do_cancel_while_reading_test (void)
soup_test_session_abort_unref (session);
}
+static void
+do_aliases_test_for_session (SoupSession *session,
+ const char *redirect_protocol)
+{
+ SoupMessage *msg;
+ SoupURI *uri;
+ const char *redirected_protocol;
+
+ uri = soup_uri_new_with_base (base_uri, "/alias-redirect");
+ msg = soup_message_new_from_uri ("GET", uri);
+ if (redirect_protocol)
+ soup_message_headers_append (msg->request_headers, "X-Redirect-Protocol", redirect_protocol);
+ soup_uri_free (uri);
+ soup_session_send_message (session, msg);
+
+ redirected_protocol = soup_message_headers_get_one (msg->response_headers, "X-Redirected-Protocol");
+
+ if (g_strcmp0 (redirect_protocol, redirected_protocol)) {
+ debug_printf (1, " redirect went to %s, should have gone to %s!\n",
+ redirected_protocol ? redirected_protocol : "(none)",
+ redirect_protocol ? redirect_protocol : "(none)");
+ errors++;
+ } else if (redirect_protocol && !SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+ debug_printf (1, " msg failed? (%d %s)\n",
+ msg->status_code, msg->reason_phrase);
+ errors++;
+ } else if (!redirect_protocol && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+ debug_printf (1, " msg succeeded? (%d %s)\n",
+ msg->status_code, msg->reason_phrase);
+ errors++;
+ }
+
+ g_object_unref (msg);
+}
+
+static void
+do_aliases_test (void)
+{
+ SoupSession *session;
+ char *aliases[] = { "foo", NULL };
+
+ debug_printf (1, "\nhttp-aliases / https-aliases\n");
+
+ debug_printf (1, " Default behavior\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ do_aliases_test_for_session (session, "http");
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " foo-means-https\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_HTTPS_ALIASES, aliases,
+ NULL);
+ do_aliases_test_for_session (session, "https");
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " foo-means-nothing\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_HTTP_ALIASES, NULL,
+ NULL);
+ do_aliases_test_for_session (session, NULL);
+ soup_test_session_abort_unref (session);
+}
+
int
main (int argc, char **argv)
{
@@ -1019,7 +1111,7 @@ main (int argc, char **argv)
test_init (argc, argv, NULL);
server = soup_test_server_new (TRUE);
- soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+ soup_server_add_handler (server, NULL, server_callback, "http", NULL);
base_uri = soup_uri_new ("http://127.0.0.1/");
soup_uri_set_port (base_uri, soup_server_get_port (server));
@@ -1031,6 +1123,11 @@ main (int argc, char **argv)
soup_server_add_auth_domain (server, auth_domain);
g_object_unref (auth_domain);
+ ssl_server = soup_test_server_new_ssl (TRUE);
+ soup_server_add_handler (ssl_server, NULL, server_callback, "https", NULL);
+ ssl_base_uri = soup_uri_new ("https://127.0.0.1/");
+ soup_uri_set_port (ssl_base_uri, soup_server_get_port (ssl_server));
+
do_host_test ();
do_callback_unref_test ();
do_msg_reuse_test ();
@@ -1041,9 +1138,12 @@ main (int argc, char **argv)
do_persistent_connection_timeout_test ();
do_max_conns_test ();
do_cancel_while_reading_test ();
+ do_aliases_test ();
soup_uri_free (base_uri);
+ soup_uri_free (ssl_base_uri);
soup_test_server_quit_unref (server);
+ soup_test_server_quit_unref (ssl_server);
test_cleanup ();
return errors != 0;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]