[libsoup/new-io: 1/2] start SoupRequest, soup_session_request_uri, etc



commit 656104c1595fa34588a783b79514571970d86c97
Author: Dan Winship <danw gnome org>
Date:   Fri Dec 18 20:03:54 2009 +0100

    start SoupRequest, soup_session_request_uri, etc

 libsoup/Makefile.am         |    4 +
 libsoup/soup-request-file.c |  201 +++++++++++++++++++++++++++++++++++++++++++
 libsoup/soup-request-file.h |   33 +++++++
 libsoup/soup-request.c      |  148 +++++++++++++++++++++++++++++++
 libsoup/soup-request.h      |   56 ++++++++++++
 libsoup/soup-session.c      |  115 ++++++++++++++++++++++++
 libsoup/soup-session.h      |   24 +++++-
 libsoup/soup-types.h        |    1 +
 libsoup/soup.h              |    1 +
 tests/get.c                 |  145 +++++++++----------------------
 10 files changed, 622 insertions(+), 106 deletions(-)
---
diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am
index 53fae83..3e7161f 100644
--- a/libsoup/Makefile.am
+++ b/libsoup/Makefile.am
@@ -75,6 +75,7 @@ soup_headers =			\
 	soup-portability.h	\
 	soup-proxy-resolver.h	\
 	soup-proxy-uri-resolver.h \
+	soup-request.h		\
 	soup-server.h		\
 	soup-session.h		\
 	soup-session-async.h	\
@@ -157,6 +158,9 @@ libsoup_2_4_la_SOURCES =		\
 	soup-proxy-resolver-static.h	\
 	soup-proxy-resolver-static.c	\
 	soup-proxy-uri-resolver.c	\
+	soup-request.c			\
+	soup-request-file.h		\
+	soup-request-file.c		\
 	soup-server.c			\
 	soup-session.c			\
 	soup-session-async.c		\
diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c
new file mode 100644
index 0000000..13f2002
--- /dev/null
+++ b/libsoup/soup-request-file.c
@@ -0,0 +1,201 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-request-file.c: file: URI request object
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include "soup-request-file.h"
+#include "soup-request.h"
+#include "soup-session-feature.h"
+#include "soup-session.h"
+#include "soup-uri.h"
+
+static void soup_request_file_request_interface_init (SoupRequestInterface *request_interface);
+static void soup_request_file_initable_interface_init (GInitableIface *initable_interface);
+
+G_DEFINE_TYPE_WITH_CODE (SoupRequestFile, soup_request_file, G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (SOUP_TYPE_REQUEST,
+						soup_request_file_request_interface_init)
+			 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+						soup_request_file_initable_interface_init))
+
+struct _SoupRequestFilePrivate {
+	SoupURI *uri;
+	GFile *gfile;
+};
+
+enum {
+	PROP_0,
+
+	PROP_URI
+};
+
+static void soup_request_file_set_property (GObject *object, guint prop_id,
+					    const GValue *value, GParamSpec *pspec);
+static void soup_request_file_get_property (GObject *object, guint prop_id,
+					    GValue *value, GParamSpec *pspec);
+static void soup_request_file_finalize (GObject *object);
+
+static gboolean soup_request_file_initable_init (GInitable     *initable,
+						 GCancellable  *cancellable,
+						 GError       **error);
+
+static GInputStream *soup_request_file_send        (SoupRequest          *request,
+						    GCancellable         *cancellable,
+						    GError              **error);
+static void          soup_request_file_send_async  (SoupRequest          *request,
+						    GCancellable         *cancellable,
+						    GAsyncReadyCallback   callback,
+						    gpointer              user_data);
+static GInputStream *soup_request_file_send_finish (SoupRequest          *request,
+						    GAsyncResult         *result,
+						    GError              **error);
+
+static void
+soup_request_file_class_init (SoupRequestFileClass *request_file_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (request_file_class);
+
+	g_type_class_add_private (request_file_class, sizeof (SoupRequestFilePrivate));
+
+	object_class->finalize = soup_request_file_finalize;
+	object_class->set_property = soup_request_file_set_property;
+	object_class->get_property = soup_request_file_get_property;
+
+	g_object_class_override_property (object_class, PROP_URI, "uri");
+}
+
+static void
+soup_request_file_request_interface_init (SoupRequestInterface *request_interface)
+{
+	request_interface->send = soup_request_file_send;
+	request_interface->send_async = soup_request_file_send_async;
+	request_interface->send_finish = soup_request_file_send_finish;
+}
+
+static void
+soup_request_file_initable_interface_init (GInitableIface *initable_interface)
+{
+	initable_interface->init = soup_request_file_initable_init;
+}
+
+static void
+soup_request_file_init (SoupRequestFile *file)
+{
+	file->priv = G_TYPE_INSTANCE_GET_PRIVATE (file, SOUP_TYPE_REQUEST_FILE, SoupRequestFilePrivate);
+}
+
+static gboolean
+soup_request_file_initable_init (GInitable     *initable,
+				 GCancellable  *cancellable,
+				 GError       **error)
+{
+	SoupRequestFile *file = SOUP_REQUEST_FILE (initable);
+	const char *host;
+	char *path_decoded;
+
+	host = file->priv->uri->host;
+	if (!host || (*host && strcmp (host, "localhost") != 0)) {
+		if (error) {
+			char *uri_string = soup_uri_to_string (file->priv->uri, FALSE);
+			g_set_error (error, SOUP_ERROR, SOUP_ERROR_BAD_URI,
+				     _("Invalid 'file' URI: %s"), uri_string);
+			g_free (uri_string);
+		}
+		return FALSE;
+	}
+
+	path_decoded = soup_uri_decode (file->priv->uri->path);
+	file->priv->gfile = g_file_new_for_path (path_decoded);
+	g_free (path_decoded);
+
+	return TRUE;
+}
+
+static void
+soup_request_file_finalize (GObject *object)
+{
+	SoupRequestFile *file = SOUP_REQUEST_FILE (object);
+
+	if (file->priv->uri)
+		soup_uri_free (file->priv->uri);
+	if (file->priv->gfile)
+		g_object_unref (file->priv->gfile);
+
+	G_OBJECT_CLASS (soup_request_file_parent_class)->finalize (object);
+}
+
+static void
+soup_request_file_set_property (GObject *object, guint prop_id,
+				const GValue *value, GParamSpec *pspec)
+{
+	SoupRequestFile *file = SOUP_REQUEST_FILE (object);
+
+	switch (prop_id) {
+	case PROP_URI:
+		if (file->priv->uri)
+			soup_uri_free (file->priv->uri);
+		file->priv->uri = g_value_dup_boxed (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+soup_request_file_get_property (GObject *object, guint prop_id,
+				GValue *value, GParamSpec *pspec)
+{
+	SoupRequestFile *file = SOUP_REQUEST_FILE (object);
+
+	switch (prop_id) {
+	case PROP_URI:
+		g_value_set_boxed (value, file->priv->uri);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static GInputStream *
+soup_request_file_send (SoupRequest          *request,
+			GCancellable         *cancellable,
+			GError              **error)
+{
+	SoupRequestFile *file = SOUP_REQUEST_FILE (request);
+
+	return (GInputStream *)g_file_read (file->priv->gfile,
+					    cancellable, error);
+}
+
+static void
+soup_request_file_send_async (SoupRequest          *request,
+			      GCancellable         *cancellable,
+			      GAsyncReadyCallback   callback,
+			      gpointer              user_data)
+{
+	SoupRequestFile *file = SOUP_REQUEST_FILE (request);
+
+	g_file_read_async (file->priv->gfile, G_PRIORITY_DEFAULT,
+			   cancellable, callback, user_data);
+}
+
+static GInputStream *
+soup_request_file_send_finish (SoupRequest          *request,
+			       GAsyncResult         *result,
+			       GError              **error)
+{
+	SoupRequestFile *file = SOUP_REQUEST_FILE (request);
+
+	return (GInputStream *)g_file_read_finish (file->priv->gfile,
+						   result, error);
+}
diff --git a/libsoup/soup-request-file.h b/libsoup/soup-request-file.h
new file mode 100644
index 0000000..7e486a2
--- /dev/null
+++ b/libsoup/soup-request-file.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifndef SOUP_REQUEST_FILE_H
+#define SOUP_REQUEST_FILE_H 1
+
+#include <libsoup/soup-types.h>
+
+#define SOUP_TYPE_REQUEST_FILE            (soup_request_file_get_type ())
+#define SOUP_REQUEST_FILE(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_REQUEST_FILE, SoupRequestFile))
+#define SOUP_REQUEST_FILE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_REQUEST_FILE, SoupRequestFileInterface))
+#define SOUP_IS_REQUEST_FILE(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_REQUEST_FILE))
+#define SOUP_IS_REQUEST_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_REQUEST_FILE))
+#define SOUP_REQUEST_FILE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SOUP_TYPE_REQUEST_FILE, SoupRequestFileInterface))
+
+typedef struct _SoupRequestFilePrivate SoupRequestFilePrivate;
+
+typedef struct {
+	GObject parent;
+
+	SoupRequestFilePrivate *priv;
+} SoupRequestFile;
+
+typedef struct {
+	GObjectClass parent;
+
+} SoupRequestFileClass;
+
+GType soup_request_file_get_type (void);
+
+#endif /* SOUP_REQUEST_FILE_H */
diff --git a/libsoup/soup-request.c b/libsoup/soup-request.c
new file mode 100644
index 0000000..06d9810
--- /dev/null
+++ b/libsoup/soup-request.c
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-request.c: Protocol-independent streaming request interface
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "soup-request.h"
+#include "soup-uri.h"
+
+/**
+ * SECTION:soup-request
+ * @short_description: Protocol-independent streaming request interface
+ *
+ * FIXME
+ **/
+
+/**
+ * SoupRequest:
+ *
+ * FIXME
+ *
+ * Since: 2.30
+ **/
+
+/**
+ * SoupRequestInterface:
+ * @parent: The parent interface.
+ * @send: Synchronously send a request
+ * @send_async: Asynchronously begin sending a request
+ * @send_finish: Get the result of asynchronously sending a request
+ *
+ * The interface implemented by #SoupRequest<!-- -->s.
+ *
+ * Since: 2.30
+ **/
+
+static void soup_request_interface_init (SoupRequestInterface *interface);
+
+static void          send_async_default  (SoupRequest          *request,
+					  GCancellable         *cancellable,
+					  GAsyncReadyCallback   callback,
+					  gpointer              user_data);
+static GInputStream *send_finish_default (SoupRequest          *request,
+					  GAsyncResult         *result,
+					  GError              **error);
+
+GType
+soup_request_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      GType g_define_type_id =
+        g_type_register_static_simple (G_TYPE_INTERFACE,
+                                       g_intern_static_string ("SoupRequest"),
+                                       sizeof (SoupRequestInterface),
+                                       (GClassInitFunc)soup_request_interface_init,
+                                       0,
+                                       (GInstanceInitFunc)NULL,
+                                       (GTypeFlags) 0);
+      g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+  return g_define_type_id__volatile;
+}
+
+static void
+soup_request_interface_init (SoupRequestInterface *interface)
+{
+	interface->send_async = send_async_default;
+	interface->send_finish = send_finish_default;
+
+	g_object_interface_install_property (
+		interface,
+		g_param_spec_boxed (SOUP_REQUEST_URI,
+				    "URI",
+				    "The request URI",
+				    SOUP_TYPE_URI,
+				    G_PARAM_READWRITE));
+}
+
+SoupURI *
+soup_request_get_uri (SoupRequest *request)
+{
+	SoupURI *uri;
+
+	g_object_get (G_OBJECT (request), "uri", &uri, NULL);
+	return uri;
+}
+
+/* Default implementation: assume the sync implementation doesn't block */
+static void
+send_async_default  (SoupRequest          *request,
+		     GCancellable         *cancellable,
+		     GAsyncReadyCallback   callback,
+		     gpointer              user_data)
+{
+	GSimpleAsyncResult *simple;
+
+	simple = g_simple_async_result_new (G_OBJECT (request),
+					    callback, user_data,
+					    send_async_default);
+	g_simple_async_result_complete_in_idle (simple);
+	g_object_unref (simple);
+}
+
+static GInputStream *
+send_finish_default (SoupRequest          *request,
+		     GAsyncResult         *result,
+		     GError              **error)
+{
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (request), send_async_default), NULL);
+
+	return soup_request_send (request, NULL, error);	
+}
+
+GInputStream *
+soup_request_send (SoupRequest          *request,
+		   GCancellable         *cancellable,
+		   GError              **error)
+{
+	return SOUP_REQUEST_GET_CLASS (request)->
+		send (request, cancellable, error);
+}
+
+void
+soup_request_send_async (SoupRequest          *request,
+			 GCancellable         *cancellable,
+			 GAsyncReadyCallback   callback,
+			 gpointer              user_data)
+{
+	SOUP_REQUEST_GET_CLASS (request)->
+		send_async (request, cancellable, callback, user_data);
+}
+
+GInputStream *
+soup_request_send_finish (SoupRequest          *request,
+			  GAsyncResult         *result,
+			  GError              **error)
+{
+	return SOUP_REQUEST_GET_CLASS (request)->
+		send_finish (request, result, error);
+}
diff --git a/libsoup/soup-request.h b/libsoup/soup-request.h
new file mode 100644
index 0000000..6dd3c63
--- /dev/null
+++ b/libsoup/soup-request.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifndef SOUP_REQUEST_H
+#define SOUP_REQUEST_H 1
+
+#include <libsoup/soup-types.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define SOUP_TYPE_REQUEST            (soup_request_get_type ())
+#define SOUP_REQUEST(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_REQUEST, SoupRequest))
+#define SOUP_REQUEST_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_REQUEST, SoupRequestInterface))
+#define SOUP_IS_REQUEST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_REQUEST))
+#define SOUP_IS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_REQUEST))
+#define SOUP_REQUEST_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SOUP_TYPE_REQUEST, SoupRequestInterface))
+
+typedef struct {
+	GTypeInterface parent;
+
+	/* methods */
+	GInputStream * (*send)        (SoupRequest          *request,
+				       GCancellable         *cancellable,
+				       GError              **error);
+	void           (*send_async)  (SoupRequest          *request,
+				       GCancellable         *cancellable,
+				       GAsyncReadyCallback   callback,
+				       gpointer              user_data);
+	GInputStream * (*send_finish) (SoupRequest          *request,
+				       GAsyncResult         *result,
+				       GError              **error);
+} SoupRequestInterface;
+
+GType soup_request_get_type (void);
+
+#define SOUP_REQUEST_URI "uri"
+
+SoupURI      *soup_request_get_uri     (SoupRequest          *request);
+
+GInputStream *soup_request_send        (SoupRequest          *request,
+					GCancellable         *cancellable,
+					GError              **error);
+void          soup_request_send_async  (SoupRequest          *request,
+					GCancellable         *cancellable,
+					GAsyncReadyCallback   callback,
+					gpointer              user_data);
+GInputStream *soup_request_send_finish (SoupRequest          *request,
+					GAsyncResult         *result,
+					GError              **error);
+
+G_END_DECLS
+
+#endif /* SOUP_REQUEST_H */
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 2b13228..1e44adf 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -13,6 +13,8 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include <glib/gi18n.h>
+
 #include "soup-address.h"
 #include "soup-auth.h"
 #include "soup-auth-basic.h"
@@ -25,6 +27,7 @@
 #include "soup-misc.h"
 #include "soup-proxy-resolver-static.h"
 #include "soup-proxy-uri-resolver.h"
+#include "soup-request-file.h"
 #include "soup-session.h"
 #include "soup-session-feature.h"
 #include "soup-session-private.h"
@@ -80,6 +83,7 @@ typedef struct {
 
 	GSList *features;
 	GHashTable *features_cache;
+	GHashTable *request_types;
 
 	GHashTable *hosts; /* char* -> SoupSessionHost */
 	GHashTable *conns; /* SoupConnection -> SoupSessionHost */
@@ -229,6 +233,8 @@ finalize (GObject *object)
 		g_main_context_unref (priv->async_context);
 
 	g_hash_table_destroy (priv->features_cache);
+	if (priv->request_types)
+		g_hash_table_destroy (priv->request_types);
 
 	g_object_unref (priv->resolver);
 
@@ -1969,3 +1975,112 @@ soup_session_get_feature_for_message (SoupSession *session, GType feature_type,
 		return NULL;
 	return feature;
 }
+
+GQuark
+soup_error_quark (void)
+{
+	static GQuark error;
+	if (!error)
+		error = g_quark_from_static_string ("soup_error_quark");
+	return error;
+}
+
+static void
+init_request_types (SoupSessionPrivate *priv)
+{
+	if (priv->request_types)
+		return;
+
+	priv->request_types = g_hash_table_new_full (soup_str_case_hash,
+						     soup_str_case_equal,
+						     g_free, NULL);
+	g_hash_table_insert (priv->request_types, "file",
+			     GSIZE_TO_POINTER (SOUP_TYPE_REQUEST_FILE));
+#if 0
+	g_hash_table_insert (priv->request_types, "data",
+			     GSIZE_TO_POINTER (SOUP_TYPE_REQUEST_DATA));
+	g_hash_table_insert (priv->request_types, "http",
+			     GSIZE_TO_POINTER (SOUP_TYPE_REQUEST_HTTP));
+	g_hash_table_insert (priv->request_types, "https",
+			     GSIZE_TO_POINTER (SOUP_TYPE_REQUEST_HTTP));
+	g_hash_table_insert (priv->request_types, "ftp",
+			     GSIZE_TO_POINTER (SOUP_TYPE_REQUEST_FTP));
+#endif
+}
+
+void
+soup_session_add_protocol (SoupSession *session,
+			   const char  *scheme,
+			   GType        request_type)
+{
+	SoupSessionPrivate *priv;
+
+	g_return_if_fail (SOUP_IS_SESSION (session));
+
+	priv = SOUP_SESSION_GET_PRIVATE (session);
+	init_request_types (priv);
+	g_hash_table_insert (priv->request_types, g_strdup (scheme),
+			     GSIZE_TO_POINTER (request_type));
+}
+
+void
+soup_session_remove_protocol (SoupSession *session,
+			      const char  *scheme)
+{
+	SoupSessionPrivate *priv;
+
+	g_return_if_fail (SOUP_IS_SESSION (session));
+
+	priv = SOUP_SESSION_GET_PRIVATE (session);
+	init_request_types (priv);
+	g_hash_table_remove (priv->request_types, scheme);
+}
+
+SoupRequest *
+soup_session_request (SoupSession        *session,
+		      const char         *uri_string,
+		      GError            **error)
+{
+	SoupURI *uri = soup_uri_new (uri_string);
+	SoupRequest *req;
+
+	if (!uri) {
+		g_set_error (error, SOUP_ERROR, SOUP_ERROR_BAD_URI,
+			     _("Could not parse URI '%s'"), uri_string);
+		return NULL;
+	}
+
+	req = soup_session_request_uri (session, uri, error);
+	soup_uri_free (uri);
+	return req;
+}
+
+SoupRequest *
+soup_session_request_uri (SoupSession        *session,
+			  SoupURI            *uri,
+			  GError            **error)
+{
+	SoupSessionPrivate *priv;
+	GType request_type;
+
+	g_return_val_if_fail (SOUP_IS_SESSION (session), NULL);
+
+	priv = SOUP_SESSION_GET_PRIVATE (session);
+	init_request_types (priv);
+	request_type = (GType) GPOINTER_TO_SIZE (g_hash_table_lookup (priv->request_types, uri->scheme));
+	if (!request_type) {
+		g_set_error (error, SOUP_ERROR, SOUP_ERROR_UNSUPPORTED_URI_SCHEME,
+			     _("Unsupported URI scheme '%s'"), uri->scheme);
+		return NULL;
+	}
+
+	if (g_type_is_a (request_type, G_TYPE_INITABLE)) {
+		return g_initable_new (request_type, NULL, error,
+				       "uri", uri,
+				       NULL);
+	} else {
+		return g_object_new (request_type,
+				     "uri", uri,
+				     NULL);
+	}
+}
diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h
index 056799d..0c68f30 100644
--- a/libsoup/soup-session.h
+++ b/libsoup/soup-session.h
@@ -49,9 +49,10 @@ typedef struct {
 	void  (*auth_required)   (SoupSession *session, SoupMessage *msg,
 				  SoupAuth *auth, gboolean retrying);
 
+	SoupRequest * (*request_uri) (SoupSession *session, SoupURI *uri,
+				      GError **error);
 
 	/* Padding for future expansion */
-	void (*_libsoup_reserved2) (void);
 	void (*_libsoup_reserved3) (void);
 	void (*_libsoup_reserved4) (void);
 } SoupSessionClass;
@@ -114,6 +115,27 @@ SoupSessionFeature *soup_session_get_feature_for_message(SoupSession        *ses
 							 GType               feature_type,
 							 SoupMessage        *msg);
 
+#define SOUP_ERROR soup_error_quark()
+GQuark soup_error_quark (void);
+
+typedef enum {
+	SOUP_ERROR_BAD_URI,
+	SOUP_ERROR_UNSUPPORTED_URI_SCHEME
+} SoupError;
+
+void soup_session_add_protocol    (SoupSession *session,
+				   const char  *scheme,
+				   GType        request_type);
+void soup_session_remove_protocol (SoupSession *session,
+				   const char  *scheme);
+
+SoupRequest        *soup_session_request                (SoupSession        *session,
+							 const char         *uri_string,
+							 GError            **error);
+SoupRequest        *soup_session_request_uri            (SoupSession        *session,
+							 SoupURI            *uri,
+							 GError            **error);
+
 G_END_DECLS
 
 #endif /* SOUP_SESSION_H */
diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h
index def6c85..6847686 100644
--- a/libsoup/soup-types.h
+++ b/libsoup/soup-types.h
@@ -20,6 +20,7 @@ typedef struct _SoupCookie            SoupCookie;
 typedef struct _SoupCookieJar         SoupCookieJar;
 typedef struct _SoupDate              SoupDate;
 typedef struct _SoupMessage           SoupMessage;
+typedef struct _SoupRequest           SoupRequest;
 typedef struct _SoupServer            SoupServer;
 typedef struct _SoupSession           SoupSession;
 typedef struct _SoupSessionAsync      SoupSessionAsync;
diff --git a/libsoup/soup.h b/libsoup/soup.h
index e727361..d63b2d8 100644
--- a/libsoup/soup.h
+++ b/libsoup/soup.h
@@ -32,6 +32,7 @@ extern "C" {
 #include <libsoup/soup-password-manager.h>
 #include <libsoup/soup-proxy-resolver.h>
 #include <libsoup/soup-proxy-uri-resolver.h>
+#include <libsoup/soup-request.h>
 #include <libsoup/soup-server.h>
 #include <libsoup/soup-session-async.h>
 #include <libsoup/soup-session-feature.h>
diff --git a/tests/get.c b/tests/get.c
index 79d6e80..188543b 100644
--- a/tests/get.c
+++ b/tests/get.c
@@ -23,104 +23,64 @@
 #endif
 
 static SoupSession *session;
-static GMainLoop *loop;
 static gboolean debug = FALSE, quiet = FALSE;
-static const char *method;
 
 static void
-get_url (const char *url)
+get_url (SoupURI *uri)
 {
-	const char *name;
-	SoupMessage *msg;
-	const char *header;
-
-	msg = soup_message_new (method, url);
-	soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
-
-	soup_session_send_message (session, msg);
-
-	name = soup_message_get_uri (msg)->path;
-
-	if (debug) {
-		SoupMessageHeadersIter iter;
-		const char *hname, *value;
-		char *path = soup_uri_to_string (soup_message_get_uri (msg), TRUE);
-
-		printf ("%s %s HTTP/1.%d\n", method, path,
-			soup_message_get_http_version (msg));
-		soup_message_headers_iter_init (&iter, msg->request_headers);
-		while (soup_message_headers_iter_next (&iter, &hname, &value))
-			printf ("%s: %s\r\n", hname, value);
-		printf ("\n");
-
-		printf ("HTTP/1.%d %d %s\n",
-			soup_message_get_http_version (msg),
-			msg->status_code, msg->reason_phrase);
-
-		soup_message_headers_iter_init (&iter, msg->response_headers);
-		while (soup_message_headers_iter_next (&iter, &hname, &value))
-			printf ("%s: %s\r\n", hname, value);
-		printf ("\n");
-	} else if (!quiet || SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
-		printf ("%s: %d %s\n", name, msg->status_code, msg->reason_phrase);
-
-	if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) {
-		header = soup_message_headers_get_one (msg->response_headers,
-						       "Location");
-		if (header) {
-			SoupURI *uri;
-			char *uri_string;
-
-			if (!debug && !quiet)
-				printf ("  -> %s\n", header);
-
-			uri = soup_uri_new_with_base (soup_message_get_uri (msg), header);
-			uri_string = soup_uri_to_string (uri, FALSE);
-			get_url (uri_string);
-			g_free (uri_string);
-			soup_uri_free (uri);
-		}
-	} else if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-		fwrite (msg->response_body->data, 1,
-			msg->response_body->length, stdout);
+	SoupRequest *req;
+	GInputStream *istream;
+	GError *error = NULL;
+	char buf[8192];
+	gsize nread;
+
+	req = soup_session_request_uri (session, uri, &error);
+	if (!req) {
+		fprintf (stderr, "Could not request URI: %s\n",
+			 error->message);
+		exit (1);
+	}
+
+	istream = soup_request_send (req, NULL, &error);
+	if (!istream) {
+		fprintf (stderr, "Could not send URI: %s\n",
+			 error->message);
+		exit (1);
+	}
+
+	while ((nread = g_input_stream_read (istream, buf, sizeof (buf),
+					     NULL, &error)) > 0)
+		fwrite (buf, 1, nread, stdout);
+
+	if (error) {
+		fprintf (stderr, "Read failed: %s\n", error->message);
+		exit (1);
 	}
 }
 
 static void
 usage (void)
 {
-	fprintf (stderr, "Usage: get [-c CAfile] [-p proxy URL] [-h] [-d] URL\n");
+	fprintf (stderr, "Usage: get [-p proxy] [-d] URL\n");
 	exit (1);
 }
 
 int
 main (int argc, char **argv)
 {
-	const char *cafile = NULL, *url;
+	const char *url;
 	SoupURI *proxy = NULL, *parsed;
-	gboolean synchronous = FALSE;
 	int opt;
 
 	g_thread_init (NULL);
 	g_type_init ();
 
-	method = SOUP_METHOD_GET;
-
-	while ((opt = getopt (argc, argv, "c:dhp:qs")) != -1) {
+	while ((opt = getopt (argc, argv, "dp:qs")) != -1) {
 		switch (opt) {
-		case 'c':
-			cafile = optarg;
-			break;
-
 		case 'd':
 			debug = TRUE;
 			break;
 
-		case 'h':
-			method = SOUP_METHOD_HEAD;
-			debug = TRUE;
-			break;
-
 		case 'p':
 			proxy = soup_uri_new (optarg);
 			if (!proxy) {
@@ -134,10 +94,6 @@ main (int argc, char **argv)
 			quiet = TRUE;
 			break;
 
-		case 's':
-			synchronous = TRUE;
-			break;
-
 		case '?':
 			usage ();
 			break;
@@ -154,31 +110,16 @@ main (int argc, char **argv)
 		fprintf (stderr, "Could not parse '%s' as a URL\n", url);
 		exit (1);
 	}
-	soup_uri_free (parsed);
 
-	if (synchronous) {
-		session = soup_session_sync_new_with_options (
-			SOUP_SESSION_SSL_CA_FILE, cafile,
-#ifdef HAVE_GNOME
-			SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_GNOME_FEATURES_2_26,
-#endif
-			SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
-			SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
-			SOUP_SESSION_USER_AGENT, "get ",
-			SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
-			NULL);
-	} else {
-		session = soup_session_async_new_with_options (
-			SOUP_SESSION_SSL_CA_FILE, cafile,
+	session = soup_session_sync_new_with_options (
 #ifdef HAVE_GNOME
-			SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_GNOME_FEATURES_2_26,
+		SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_GNOME_FEATURES_2_26,
 #endif
-			SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
-			SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
-			SOUP_SESSION_USER_AGENT, "get ",
-			SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
-			NULL);
-	}
+		SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
+		SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
+		SOUP_SESSION_USER_AGENT, "get ",
+		SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
+		NULL);
 
 	/* Need to do this after creating the session, since adding
 	 * SOUP_TYPE_GNOME_FEATURE_2_26 will add a proxy resolver, thereby
@@ -190,13 +131,7 @@ main (int argc, char **argv)
 			      NULL);
 	}
 
-	if (!synchronous)
-		loop = g_main_loop_new (NULL, TRUE);
-
-	get_url (url);
-
-	if (!synchronous)
-		g_main_loop_unref (loop);
-
+	get_url (parsed);
+	soup_uri_free (parsed);
 	return 0;
 }



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