summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2012-08-26 15:20:34 +0200
committerCarlos Garcia Campos <carlosgc@gnome.org>2012-10-20 11:34:18 +0200
commitcbbde758b8ea533916fe25dc25d64bac564ea09a (patch)
tree48d74c0deed1885a5230ddcf897f4632bbbda257
parentaa8e1dc5127b56bd96e9d3068a6bfeb7c1a07a94 (diff)
downloadlibsoup-cbbde758b8ea533916fe25dc25d64bac564ea09a.tar.gz
libsoup-cbbde758b8ea533916fe25dc25d64bac564ea09a.tar.bz2
libsoup-cbbde758b8ea533916fe25dc25d64bac564ea09a.zip
soup-request: Add support to handle gresource URI requests
GFile already supports gresource when using g_file_new_for_uri() with a resource:// URI. We can add "resource" as a valid scheme for SoupRequestFile and make sure the GFile is created with the gresource URI for gresource requests. https://bugzilla.gnome.org/show_bug.cgi?id=682721
-rw-r--r--configure.ac3
-rw-r--r--docs/reference/libsoup-2.4-sections.txt1
-rw-r--r--libsoup/soup-request-file.c12
-rw-r--r--libsoup/soup-uri.c13
-rw-r--r--libsoup/soup-uri.h13
-rw-r--r--tests/Makefile.am29
-rw-r--r--tests/resource-test.c296
-rw-r--r--tests/soup-tests.gresource.xml6
8 files changed, 355 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac
index f0945875..a6b2b708 100644
--- a/configure.ac
+++ b/configure.ac
@@ -307,6 +307,9 @@ else
fi
AM_CONDITIONAL(HAVE_CURL, test "$CURL" != no)
+GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0`
+AC_SUBST(GLIB_COMPILE_RESOURCES)
+
AC_SUBST(MISSING_REGRESSION_TEST_PACKAGES)
AM_CONDITIONAL(MISSING_REGRESSION_TEST_PACKAGES, test -n "$MISSING_REGRESSION_TEST_PACKAGES")
diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt
index 6f819c32..961e4163 100644
--- a/docs/reference/libsoup-2.4-sections.txt
+++ b/docs/reference/libsoup-2.4-sections.txt
@@ -631,6 +631,7 @@ SOUP_URI_SCHEME_HTTPS
SOUP_URI_SCHEME_DATA
SOUP_URI_SCHEME_FILE
SOUP_URI_SCHEME_FTP
+SOUP_URI_SCHEME_RESOURCE
soup_uri_uses_default_port
SOUP_URI_IS_VALID
SOUP_URI_VALID_FOR_HTTP
diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c
index 0b5638d2..73d0cd8c 100644
--- a/libsoup/soup-request-file.c
+++ b/libsoup/soup-request-file.c
@@ -128,7 +128,15 @@ soup_request_file_ensure_file (SoupRequestFile *file,
windowsify_file_uri_path (decoded_path);
#endif
- file->priv->gfile = g_file_new_for_path (decoded_path);
+ if (uri->scheme == SOUP_URI_SCHEME_RESOURCE) {
+ char *uri_str;
+
+ uri_str = g_strdup_printf ("resource://%s", decoded_path);
+ file->priv->gfile = g_file_new_for_uri (uri_str);
+ g_free (uri_str);
+ } else
+ file->priv->gfile = g_file_new_for_path (decoded_path);
+
g_free (decoded_path);
return TRUE;
}
@@ -250,7 +258,7 @@ soup_request_file_get_content_type (SoupRequest *request)
return file->priv->mime_type;
}
-static const char *file_schemes[] = { "file", NULL };
+static const char *file_schemes[] = { "file", "resource", NULL };
static void
soup_request_file_class_init (SoupRequestFileClass *request_file_class)
diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c
index 4be679d5..d19290b0 100644
--- a/libsoup/soup-uri.c
+++ b/libsoup/soup-uri.c
@@ -110,7 +110,7 @@ static char *uri_normalized_copy (const char *str, int length, const char *unesc
gpointer _SOUP_URI_SCHEME_HTTP, _SOUP_URI_SCHEME_HTTPS;
gpointer _SOUP_URI_SCHEME_FTP;
-gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA;
+gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA, _SOUP_URI_SCHEME_RESOURCE;
static inline const char *
soup_uri_parse_scheme (const char *scheme, int len)
@@ -119,6 +119,8 @@ soup_uri_parse_scheme (const char *scheme, int len)
return SOUP_URI_SCHEME_HTTP;
} else if (len == 5 && !g_ascii_strncasecmp (scheme, "https", len)) {
return SOUP_URI_SCHEME_HTTPS;
+ } else if (len == 8 && !g_ascii_strncasecmp (scheme, "resource", len)) {
+ return SOUP_URI_SCHEME_RESOURCE;
} else {
char *lower_scheme;
@@ -815,6 +817,15 @@ soup_uri_uses_default_port (SoupURI *uri)
**/
/**
+ * SOUP_URI_SCHEME_RESOURCE:
+ *
+ * "resource" as an interned string. This can be compared directly
+ * against the value of a #SoupURI's <structfield>scheme</structfield>
+ *
+ * Since: 2.42
+ **/
+
+/**
* soup_uri_get_scheme:
* @uri: a #SoupURI
*
diff --git a/libsoup/soup-uri.h b/libsoup/soup-uri.h
index b851dbec..e2195b16 100644
--- a/libsoup/soup-uri.h
+++ b/libsoup/soup-uri.h
@@ -31,14 +31,15 @@ struct _SoupURI {
GType soup_uri_get_type (void);
#define SOUP_TYPE_URI (soup_uri_get_type ())
-#define SOUP_URI_SCHEME_HTTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTP, "http")
-#define SOUP_URI_SCHEME_HTTPS _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTPS, "https")
-#define SOUP_URI_SCHEME_FTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FTP, "ftp")
-#define SOUP_URI_SCHEME_FILE _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FILE, "file")
-#define SOUP_URI_SCHEME_DATA _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_DATA, "data")
+#define SOUP_URI_SCHEME_HTTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTP, "http")
+#define SOUP_URI_SCHEME_HTTPS _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTPS, "https")
+#define SOUP_URI_SCHEME_FTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FTP, "ftp")
+#define SOUP_URI_SCHEME_FILE _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FILE, "file")
+#define SOUP_URI_SCHEME_DATA _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_DATA, "data")
+#define SOUP_URI_SCHEME_RESOURCE _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_RESOURCE, "resource")
extern gpointer _SOUP_URI_SCHEME_HTTP, _SOUP_URI_SCHEME_HTTPS;
extern gpointer _SOUP_URI_SCHEME_FTP;
-extern gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA;
+extern gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA, _SOUP_URI_SCHEME_RESOURCE;
SoupURI *soup_uri_new_with_base (SoupURI *base,
const char *uri_string);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d2a1cd64..085a81b3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -28,6 +28,7 @@ noinst_PROGRAMS = \
ntlm-test \
redirect-test \
requester-test \
+ resource-test \
simple-httpd \
simple-proxy \
sniffing-test \
@@ -41,6 +42,8 @@ noinst_PROGRAMS = \
$(APACHE_TESTS) \
$(XMLRPC_TESTS)
+noinst_DATA = soup-tests.gresource
+
TEST_SRCS = test-utils.c test-utils.h
auth_test_SOURCES = auth-test.c $(TEST_SRCS)
@@ -66,6 +69,7 @@ pull_api_SOURCES = pull-api.c $(TEST_SRCS)
range_test_SOURCES = range-test.c $(TEST_SRCS)
redirect_test_SOURCES = redirect-test.c $(TEST_SRCS)
requester_test_SOURCES = requester-test.c $(TEST_SRCS)
+resource_test_SOURCES = resource-test.c $(TEST_SRCS)
server_auth_test_SOURCES = server-auth-test.c $(TEST_SRCS)
simple_httpd_SOURCES = simple-httpd.c
simple_proxy_SOURCES = simple-proxy.c
@@ -89,6 +93,9 @@ if HAVE_XMLRPC_EPI_PHP
XMLRPC_TESTS = xmlrpc-test xmlrpc-server-test
endif
+soup-tests.gresource: soup-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml)
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $<
+
TESTS = \
chunk-test \
coding-test \
@@ -103,6 +110,7 @@ TESTS = \
ntlm-test \
redirect-test \
requester-test \
+ resource-test \
sniffing-test \
socket-test \
ssl-test \
@@ -127,17 +135,20 @@ RESOURCES = \
resources/test.html \
resources/text_binary.txt
-EXTRA_DIST = \
- htdigest \
- htpasswd \
- httpd.conf.in \
- index.txt \
- libsoup.supp \
- test-cert.pem \
- test-key.pem \
- xmlrpc-server.php \
+EXTRA_DIST = \
+ htdigest \
+ htpasswd \
+ httpd.conf.in \
+ index.txt \
+ libsoup.supp \
+ soup-tests.gresource.xml \
+ test-cert.pem \
+ test-key.pem \
+ xmlrpc-server.php \
$(RESOURCES)
+DISTCLEANFILES = soup-tests.gresource
+
if MISSING_REGRESSION_TEST_PACKAGES
check-local: check-TESTS
@echo ""
diff --git a/tests/resource-test.c b/tests/resource-test.c
new file mode 100644
index 00000000..449820a4
--- /dev/null
+++ b/tests/resource-test.c
@@ -0,0 +1,296 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ */
+
+#include "test-utils.h"
+
+SoupBuffer *index_buffer;
+
+static void
+get_index (void)
+{
+ char *contents;
+ gsize length;
+ GError *error = NULL;
+
+ if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) {
+ g_printerr ("Could not read index.txt: %s\n",
+ error->message);
+ exit (1);
+ }
+
+ index_buffer = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length);
+}
+
+static void
+register_gresource (void)
+{
+ GResource *resource;
+ GError *error = NULL;
+
+ resource = g_resource_load ("soup-tests.gresource", &error);
+ if (!resource) {
+ g_printerr ("Could not load resource soup-tests.gresource: %s\n",
+ error->message);
+ exit (1);
+ }
+ g_resources_register (resource);
+ g_resource_unref (resource);
+}
+
+static void
+check_results (GString *body)
+{
+ if (body->len != index_buffer->length) {
+ debug_printf (1, " body length mismatch: expected %d, got %d\n",
+ (int)index_buffer->length, (int)body->len);
+ errors++;
+ } else if (memcmp (body->str, index_buffer->data, body->len) != 0) {
+ debug_printf (1, " body data mismatch\n");
+ errors++;
+ }
+}
+
+typedef struct {
+ GString *body;
+ char buffer[1024];
+ GMainLoop *loop;
+} AsyncRequestData;
+
+static void
+stream_closed (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GInputStream *in = G_INPUT_STREAM (source);
+ AsyncRequestData *data = user_data;
+ GError *error = NULL;
+
+ if (!g_input_stream_close_finish (in, result, &error)) {
+ debug_printf (1, " close failed: %s\n", error->message);
+ g_error_free (error);
+ errors++;
+ }
+ g_main_loop_quit (data->loop);
+ g_object_unref (in);
+}
+
+static void
+test_read_ready (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GInputStream *in = G_INPUT_STREAM (source);
+ AsyncRequestData *data = user_data;
+ gssize nread;
+ GError *error = NULL;
+
+ nread = g_input_stream_read_finish (in, result, &error);
+ if (nread == -1) {
+ debug_printf (1, " g_input_stream_read failed: %s\n",
+ error->message);
+ g_clear_error (&error);
+ g_input_stream_close (in, NULL, NULL);
+ g_object_unref (in);
+ errors++;
+ return;
+ } else if (nread == 0) {
+ g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL,
+ stream_closed, data);
+ return;
+ }
+
+ g_string_append_len (data->body, data->buffer, nread);
+ g_input_stream_read_async (in, data->buffer, sizeof (data->buffer),
+ G_PRIORITY_DEFAULT, NULL,
+ test_read_ready, data);
+}
+
+static void
+async_request_sent (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GInputStream *in;
+ AsyncRequestData *data = user_data;
+ GError *error = NULL;
+
+ in = soup_request_send_finish (SOUP_REQUEST (source), result, &error);
+ if (!in) {
+ debug_printf (1, " soup_request_send_async failed: %s\n",
+ error->message);
+ g_clear_error (&error);
+ errors++;
+ return;
+ }
+
+ g_input_stream_read_async (in, data->buffer, sizeof (data->buffer),
+ G_PRIORITY_DEFAULT, NULL,
+ test_read_ready, data);
+}
+
+static void
+do_async_request (SoupRequest *request)
+{
+ AsyncRequestData data;
+
+ data.body = g_string_new (NULL);
+ soup_request_send_async (request, NULL, async_request_sent, &data);
+
+ data.loop = g_main_loop_new (soup_session_get_async_context (soup_request_get_session (request)), TRUE);
+ g_main_loop_run (data.loop);
+ g_main_loop_unref (data.loop);
+
+ check_results (data.body);
+ g_string_free (data.body, TRUE);
+}
+
+static void
+do_sync_request (SoupRequest *request)
+{
+ GInputStream *in;
+ GString *body;
+ char buffer[1024];
+ gssize nread;
+ GError *error = NULL;
+
+ in = soup_request_send (request, NULL, &error);
+ if (!in) {
+ debug_printf (1, " soup_request_send failed: %s\n",
+ error->message);
+ g_clear_error (&error);
+ errors++;
+ return;
+ }
+
+ body = g_string_new (NULL);
+ do {
+ nread = g_input_stream_read (in, buffer, sizeof (buffer),
+ NULL, &error);
+ if (nread == -1) {
+ debug_printf (1, " g_input_stream_read failed: %s\n",
+ error->message);
+ g_clear_error (&error);
+ errors++;
+ break;
+ }
+ g_string_append_len (body, buffer, nread);
+ } while (nread > 0);
+
+ if (!g_input_stream_close (in, NULL, &error)) {
+ debug_printf (1, " g_input_stream_close failed: %s\n",
+ error->message);
+ g_clear_error (&error);
+ errors++;
+ }
+ g_object_unref (in);
+
+ check_results (body);
+ g_string_free (body, TRUE);
+}
+
+static void
+do_request_file_test (SoupRequester *requester,
+ gboolean async)
+{
+ SoupRequest *request;
+ GFile *index;
+ char *uri_string;
+ SoupURI *uri;
+
+ index = g_file_new_for_path (SRCDIR "/index.txt");
+ uri_string = g_file_get_uri (index);
+ g_object_unref (index);
+
+ uri = soup_uri_new (uri_string);
+ g_free (uri_string);
+
+ request = soup_requester_request_uri (requester, uri, NULL);
+ if (async)
+ do_async_request (request);
+ else
+ do_sync_request (request);
+ g_object_unref (request);
+
+ soup_uri_free (uri);
+}
+
+static void
+do_request_data_test (SoupRequester *requester,
+ gboolean async)
+{
+ SoupRequest *request;
+ gchar *base64;
+ char *uri_string;
+ SoupURI *uri;
+
+ base64 = g_base64_encode ((const guchar *)index_buffer->data, index_buffer->length);
+ uri_string = g_strdup_printf ("data:text/plain;charset=utf8;base64,%s", base64);
+ g_free (base64);
+
+ uri = soup_uri_new (uri_string);
+ g_free (uri_string);
+
+ request = soup_requester_request_uri (requester, uri, NULL);
+ if (async)
+ do_async_request (request);
+ else
+ do_sync_request (request);
+ g_object_unref (request);
+
+ soup_uri_free (uri);
+}
+
+static void
+do_request_gresource_test (SoupRequester *requester,
+ gboolean async)
+{
+ SoupRequest *request;
+ SoupURI *uri;
+
+ uri = soup_uri_new ("resource:///org/gnome/libsoup/tests/index.txt");
+ request = soup_requester_request_uri (requester, uri, NULL);
+ if (async)
+ do_async_request (request);
+ else
+ do_sync_request (request);
+ g_object_unref (request);
+
+ soup_uri_free (uri);
+}
+
+int
+main (int argc, char **argv)
+{
+ SoupSession *session;
+ SoupRequester *requester;
+
+ test_init (argc, argv, NULL);
+
+ get_index ();
+ register_gresource ();
+
+ /* Sync tests */
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+ requester = soup_requester_new ();
+ soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
+ g_object_unref (requester);
+
+ do_request_file_test (requester, FALSE);
+ do_request_data_test (requester, FALSE);
+ do_request_gresource_test (requester, FALSE);
+
+ soup_test_session_abort_unref (session);
+
+ /* Async tests */
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
+ requester = soup_requester_new ();
+ soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
+ g_object_unref (requester);
+
+ do_request_file_test (requester, TRUE);
+ do_request_data_test (requester, TRUE);
+ do_request_gresource_test (requester, TRUE);
+
+ soup_test_session_abort_unref (session);
+
+ test_cleanup ();
+ return errors != 0;
+}
diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml
new file mode 100644
index 00000000..969a6bfe
--- /dev/null
+++ b/tests/soup-tests.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/libsoup/tests">
+ <file>index.txt</file>
+ </gresource>
+</gresources> \ No newline at end of file