fixed typo enable_sqllite -> enable_sqlite
[platform/upstream/libsoup.git] / libsoup / soup-request.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-request.c: Protocol-independent streaming request interface
4  *
5  * Copyright (C) 2009, 2010 Red Hat, Inc.
6  * Copyright (C) 2010, Igalia S.L.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <glib/gi18n-lib.h>
29
30 #include "soup-request.h"
31 #include "soup.h"
32 #include "soup-requester.h"
33
34 /**
35  * SECTION:soup-request
36  * @short_description: Protocol-independent streaming request interface
37  *
38  * A #SoupRequest is created by #SoupSession, and represents a request
39  * to retrieve a particular URI.
40  */
41
42 /**
43  * SoupRequest:
44  *
45  * A request to retrieve a particular URI.
46  *
47  * Since: 2.42
48  */
49
50 static void soup_request_initable_interface_init (GInitableIface *initable_interface);
51
52 G_DEFINE_TYPE_WITH_CODE (SoupRequest, soup_request, G_TYPE_OBJECT,
53                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
54                                                 soup_request_initable_interface_init))
55
56 enum {
57         PROP_0,
58         PROP_URI,
59         PROP_SESSION
60 };
61
62 struct _SoupRequestPrivate {
63         SoupURI *uri;
64         SoupSession *session;
65 };
66
67 static void
68 soup_request_init (SoupRequest *request)
69 {
70         request->priv = G_TYPE_INSTANCE_GET_PRIVATE (request, SOUP_TYPE_REQUEST, SoupRequestPrivate);
71 }
72
73 static void
74 soup_request_finalize (GObject *object)
75 {
76         SoupRequest *request = SOUP_REQUEST (object);
77
78         g_clear_pointer (&request->priv->uri, soup_uri_free);
79         g_clear_object (&request->priv->session);
80
81         G_OBJECT_CLASS (soup_request_parent_class)->finalize (object);
82 }
83
84 static void
85 soup_request_set_property (GObject      *object,
86                            guint prop_id,
87                            const GValue *value,
88                            GParamSpec   *pspec)
89 {
90         SoupRequest *request = SOUP_REQUEST (object);
91
92         switch (prop_id) {
93         case PROP_URI:
94                 if (request->priv->uri)
95                         soup_uri_free (request->priv->uri);
96                 request->priv->uri = g_value_dup_boxed (value);
97                 break;
98         case PROP_SESSION:
99                 if (request->priv->session)
100                         g_object_unref (request->priv->session);
101                 request->priv->session = g_value_dup_object (value);
102                 break;
103         default:
104                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
105                 break;
106         }
107 }
108
109 static void
110 soup_request_get_property (GObject    *object,
111                            guint prop_id,
112                            GValue     *value,
113                            GParamSpec *pspec)
114 {
115         SoupRequest *request = SOUP_REQUEST (object);
116
117         switch (prop_id) {
118         case PROP_URI:
119                 g_value_set_boxed (value, request->priv->uri);
120                 break;
121         case PROP_SESSION:
122                 g_value_set_object (value, request->priv->session);
123                 break;
124         default:
125                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
126                 break;
127         }
128 }
129
130 static gboolean
131 soup_request_initable_init (GInitable     *initable,
132                             GCancellable  *cancellable,
133                             GError       **error)
134 {
135         SoupRequest *request = SOUP_REQUEST (initable);
136         gboolean ok;
137
138         if (!request->priv->uri) {
139                 g_set_error (error, SOUP_REQUEST_ERROR, SOUP_REQUEST_ERROR_BAD_URI,
140                              _("No URI provided"));
141                 return FALSE;
142         }
143
144         ok = SOUP_REQUEST_GET_CLASS (initable)->
145                 check_uri (request, request->priv->uri, error);
146
147         if (!ok && error && !*error) {
148                 char *uri_string = soup_uri_to_string (request->priv->uri, FALSE);
149                 g_set_error (error, SOUP_REQUEST_ERROR, SOUP_REQUEST_ERROR_BAD_URI,
150                              _("Invalid '%s' URI: %s"),
151                              request->priv->uri->scheme,
152                              uri_string);
153                 g_free (uri_string);
154         }
155
156         return ok;
157 }
158
159 static gboolean
160 soup_request_default_check_uri (SoupRequest  *request,
161                                 SoupURI      *uri,
162                                 GError      **error)
163 {
164         return TRUE;
165 }
166
167 /* Default implementation: assume the sync implementation doesn't block */
168 static void
169 soup_request_default_send_async (SoupRequest          *request,
170                                  GCancellable         *cancellable,
171                                  GAsyncReadyCallback   callback,
172                                  gpointer              user_data)
173 {
174         GTask *task;
175         GInputStream *stream;
176         GError *error = NULL;
177
178         task = g_task_new (request, cancellable, callback, user_data);
179
180         stream = soup_request_send (request, cancellable, &error);
181         if (stream)
182                 g_task_return_pointer (task, stream, g_object_unref);
183         else
184                 g_task_return_error (task, error);
185         g_object_unref (task);
186 }
187
188 static GInputStream *
189 soup_request_default_send_finish (SoupRequest          *request,
190                                   GAsyncResult         *result,
191                                   GError              **error)
192 {
193         return g_task_propagate_pointer (G_TASK (result), error);
194 }
195
196 /**
197  * soup_request_send:
198  * @request: a #SoupRequest
199  * @cancellable: a #GCancellable or %NULL
200  * @error: return location for a #GError, or %NULL
201  *
202  * Synchronously requests the URI pointed to by @request, and returns
203  * a #GInputStream that can be used to read its contents.
204  *
205  * Note that you cannot use this method with #SoupRequests attached to
206  * a #SoupSessionAsync.
207  *
208  * Return value: (transfer full): a #GInputStream that can be used to
209  *   read from the URI pointed to by @request.
210  *
211  * Since: 2.42
212  */
213 GInputStream *
214 soup_request_send (SoupRequest          *request,
215                    GCancellable         *cancellable,
216                    GError              **error)
217 {
218         return SOUP_REQUEST_GET_CLASS (request)->
219                 send (request, cancellable, error);
220 }
221
222 /**
223  * soup_request_send_async:
224  * @request: a #SoupRequest
225  * @cancellable: a #GCancellable or %NULL
226  * @callback: a #GAsyncReadyCallback
227  * @user_data: user data passed to @callback
228  *
229  * Begins an asynchronously request for the URI pointed to by
230  * @request.
231  *
232  * Note that you cannot use this method with #SoupRequests attached to
233  * a #SoupSessionSync.
234  *
235  * Since: 2.42
236  */
237 void
238 soup_request_send_async (SoupRequest         *request,
239                          GCancellable        *cancellable,
240                          GAsyncReadyCallback  callback,
241                          gpointer             user_data)
242 {
243         SOUP_REQUEST_GET_CLASS (request)->
244                 send_async (request, cancellable, callback, user_data);
245 }
246
247 /**
248  * soup_request_send_finish:
249  * @request: a #SoupRequest
250  * @result: the #GAsyncResult
251  * @error: return location for a #GError, or %NULL
252  *
253  * Gets the result of a soup_request_send_async().
254  *
255  * Return value: (transfer full): a #GInputStream that can be used to
256  *   read from the URI pointed to by @request.
257  *
258  * Since: 2.42
259  */
260 GInputStream *
261 soup_request_send_finish (SoupRequest          *request,
262                           GAsyncResult         *result,
263                           GError              **error)
264 {
265         return SOUP_REQUEST_GET_CLASS (request)->
266                 send_finish (request, result, error);
267 }
268
269 static void
270 soup_request_class_init (SoupRequestClass *request_class)
271 {
272         GObjectClass *object_class = G_OBJECT_CLASS (request_class);
273
274         g_type_class_add_private (request_class, sizeof (SoupRequestPrivate));
275
276         request_class->check_uri = soup_request_default_check_uri;
277         request_class->send_async = soup_request_default_send_async;
278         request_class->send_finish = soup_request_default_send_finish;
279
280         object_class->finalize = soup_request_finalize;
281         object_class->set_property = soup_request_set_property;
282         object_class->get_property = soup_request_get_property;
283
284         /**
285          * SOUP_REQUEST_URI:
286          *
287          * Alias for the #SoupRequest:uri property, qv.
288          *
289          * Since: 2.42
290          */
291         /**
292          * SoupRequest:uri:
293          *
294          * The request URI.
295          *
296          * Since: 2.42
297          */
298         g_object_class_install_property (
299                  object_class, PROP_URI,
300                  g_param_spec_boxed (SOUP_REQUEST_URI,
301                                      "URI",
302                                      "The request URI",
303                                      SOUP_TYPE_URI,
304                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
305         /**
306          * SOUP_REQUEST_SESSION:
307          *
308          * Alias for the #SoupRequest:session property, qv.
309          *
310          * Since: 2.42
311          */
312         /**
313          * SoupRequest:session:
314          *
315          * The request's #SoupSession.
316          *
317          * Since: 2.42
318          */
319         g_object_class_install_property (
320                  object_class, PROP_SESSION,
321                  g_param_spec_object (SOUP_REQUEST_SESSION,
322                                       "Session",
323                                       "The request's session",
324                                       SOUP_TYPE_SESSION,
325                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
326 }
327
328 static void
329 soup_request_initable_interface_init (GInitableIface *initable_interface)
330 {
331         initable_interface->init = soup_request_initable_init;
332 }
333
334 /**
335  * soup_request_get_uri:
336  * @request: a #SoupRequest
337  *
338  * Gets @request's URI
339  *
340  * Return value: (transfer none): @request's URI
341  *
342  * Since: 2.42
343  */
344 SoupURI *
345 soup_request_get_uri (SoupRequest *request)
346 {
347         return request->priv->uri;
348 }
349
350 /**
351  * soup_request_get_session:
352  * @request: a #SoupRequest
353  *
354  * Gets @request's #SoupSession
355  *
356  * Return value: (transfer none): @request's #SoupSession
357  *
358  * Since: 2.42
359  */
360 SoupSession *
361 soup_request_get_session (SoupRequest *request)
362 {
363         return request->priv->session;
364 }
365
366 /**
367  * soup_request_get_content_length:
368  * @request: a #SoupRequest
369  *
370  * Gets the length of the data represented by @request. For most
371  * request types, this will not be known until after you call
372  * soup_request_send() or soup_request_send_finish().
373  *
374  * Return value: the length of the data represented by @request,
375  *   or -1 if not known.
376  *
377  * Since: 2.42
378  */
379 goffset
380 soup_request_get_content_length (SoupRequest *request)
381 {
382         return SOUP_REQUEST_GET_CLASS (request)->get_content_length (request);
383 }
384
385 /**
386  * soup_request_get_content_type:
387  * @request: a #SoupRequest
388  *
389  * Gets the type of the data represented by @request. For most request
390  * types, this will not be known until after you call
391  * soup_request_send() or soup_request_send_finish().
392  *
393  * As in the HTTP Content-Type header, this may include parameters
394  * after the MIME type.
395  *
396  * Return value: the type of the data represented by @request,
397  *   or %NULL if not known.
398  *
399  * Since: 2.42
400  */
401 const char *
402 soup_request_get_content_type (SoupRequest  *request)
403 {
404         return SOUP_REQUEST_GET_CLASS (request)->get_content_type (request);
405 }