[libsoup/new-io: 1/2] start SoupRequest, soup_session_request_uri, etc
- From: Dan Winship <danw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [libsoup/new-io: 1/2] start SoupRequest, soup_session_request_uri, etc
- Date: Sun, 20 Dec 2009 10:18:58 +0000 (UTC)
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]