1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
5 * Copyright (C) 2010, Igalia S.L.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
25 #include <glib/gi18n-lib.h>
27 #define LIBSOUP_USE_UNSTABLE_REQUEST_API
29 #include "soup-requester.h"
30 #include "soup-request-data.h"
31 #include "soup-request-file.h"
32 #include "soup-request-http.h"
33 #include "soup-session-feature.h"
36 static SoupSessionFeatureInterface *soup_requester_default_feature_interface;
37 static void soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
39 struct _SoupRequesterPrivate {
41 GHashTable *request_types;
44 G_DEFINE_TYPE_WITH_CODE (SoupRequester, soup_requester, G_TYPE_OBJECT,
45 G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
46 soup_requester_session_feature_init))
49 soup_requester_init (SoupRequester *requester)
51 SoupSessionFeature *feature;
53 requester->priv = G_TYPE_INSTANCE_GET_PRIVATE (requester,
55 SoupRequesterPrivate);
57 requester->priv->request_types = g_hash_table_new (soup_str_case_hash,
60 feature = SOUP_SESSION_FEATURE (requester);
61 soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_HTTP);
62 soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_FILE);
63 soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_DATA);
67 finalize (GObject *object)
69 SoupRequester *requester = SOUP_REQUESTER (object);
71 g_hash_table_destroy (requester->priv->request_types);
73 G_OBJECT_CLASS (soup_requester_parent_class)->finalize (object);
77 soup_requester_class_init (SoupRequesterClass *requester_class)
79 GObjectClass *object_class = G_OBJECT_CLASS (requester_class);
81 g_type_class_add_private (requester_class, sizeof (SoupRequesterPrivate));
83 /* virtual method override */
84 object_class->finalize = finalize;
88 attach (SoupSessionFeature *feature, SoupSession *session)
90 SoupRequester *requester = SOUP_REQUESTER (feature);
92 requester->priv->session = session;
94 soup_requester_default_feature_interface->attach (feature, session);
98 detach (SoupSessionFeature *feature, SoupSession *session)
100 SoupRequester *requester = SOUP_REQUESTER (feature);
102 requester->priv->session = NULL;
104 soup_requester_default_feature_interface->detach (feature, session);
108 add_feature (SoupSessionFeature *feature, GType type)
110 SoupRequester *requester = SOUP_REQUESTER (feature);
111 SoupRequestClass *request_class;
114 if (!g_type_is_a (type, SOUP_TYPE_REQUEST))
117 request_class = g_type_class_ref (type);
118 for (i = 0; request_class->schemes[i]; i++) {
119 g_hash_table_insert (requester->priv->request_types,
120 (char *)request_class->schemes[i],
121 GSIZE_TO_POINTER (type));
127 remove_feature (SoupSessionFeature *feature, GType type)
129 SoupRequester *requester = SOUP_REQUESTER (feature);
130 SoupRequestClass *request_class;
133 if (!g_type_is_a (type, SOUP_TYPE_REQUEST))
136 request_class = g_type_class_peek (type);
140 orig_size = g_hash_table_size (requester->priv->request_types);
141 for (i = 0; request_class->schemes[i]; i++) {
142 g_hash_table_remove (requester->priv->request_types,
143 request_class->schemes[i]);
146 return g_hash_table_size (requester->priv->request_types) != orig_size;
150 has_feature (SoupSessionFeature *feature, GType type)
152 SoupRequester *requester = SOUP_REQUESTER (feature);
156 if (!g_type_is_a (type, SOUP_TYPE_REQUEST))
159 g_hash_table_iter_init (&iter, requester->priv->request_types);
160 while (g_hash_table_iter_next (&iter, &key, &value)) {
161 if (value == GSIZE_TO_POINTER (type))
168 soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface,
169 gpointer interface_data)
171 soup_requester_default_feature_interface =
172 g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE);
174 feature_interface->attach = attach;
175 feature_interface->detach = detach;
176 feature_interface->add_feature = add_feature;
177 feature_interface->remove_feature = remove_feature;
178 feature_interface->has_feature = has_feature;
182 * soup_requester_new:
184 * Creates a new #SoupRequester object, which can be added to
185 * a #SoupSession with soup_session_add_feature().
187 * Return value: the new #SoupRequester
192 soup_requester_new (void)
194 return g_object_new (SOUP_TYPE_REQUESTER, NULL);
198 * soup_requester_request:
199 * @requester: a #SoupRequester
200 * @uri_string: a URI, in string form
201 * @error: return location for a #GError, or %NULL
203 * Creates a #SoupRequest for retrieving @uri_string.
205 * Return value: (transfer full): a new #SoupRequest, or
211 soup_requester_request (SoupRequester *requester, const char *uri_string,
217 uri = soup_uri_new (uri_string);
219 g_set_error (error, SOUP_REQUESTER_ERROR, SOUP_REQUESTER_ERROR_BAD_URI,
220 _("Could not parse URI '%s'"), uri_string);
224 req = soup_requester_request_uri (requester, uri, error);
230 * soup_requester_request_uri:
231 * @requester: a #SoupRequester
232 * @uri: a #SoupURI representing the URI to retrieve
233 * @error: return location for a #GError, or %NULL
235 * Creates a #SoupRequest for retrieving @uri.
237 * Return value: (transfer full): a new #SoupRequest, or
243 soup_requester_request_uri (SoupRequester *requester, SoupURI *uri,
248 g_return_val_if_fail (SOUP_IS_REQUESTER (requester), NULL);
250 request_type = (GType)GPOINTER_TO_SIZE (g_hash_table_lookup (requester->priv->request_types, uri->scheme));
252 g_set_error (error, SOUP_REQUESTER_ERROR,
253 SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME,
254 _("Unsupported URI scheme '%s'"), uri->scheme);
258 return g_initable_new (request_type, NULL, error,
260 "session", requester->priv->session,
265 * SOUP_REQUESTER_ERROR:
267 * A #GError domain for #SoupRequester errors. Used with
268 * #SoupRequesterError.
273 * SoupRequesterError:
274 * @SOUP_REQUESTER_ERROR_BAD_URI: the URI could not be parsed
275 * @SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME: the URI scheme is not
276 * supported by this #SoupRequester
278 * A #SoupRequester error.
284 soup_requester_error_quark (void)
288 error = g_quark_from_static_string ("soup_requester_error_quark");