2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
3 "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
4 <refentry id="libsoup-client-howto">
6 <refentrytitle>Soup Client Basics</refentrytitle>
7 <manvolnum>3</manvolnum>
8 <refmiscinfo>LIBSOUP Library</refmiscinfo>
12 <refname>Soup Client Basics</refname><refpurpose>Client-side tutorial</refpurpose>
16 <title>Creating a <type>SoupSession</type></title>
19 The first step in using the client API is to create a <link
20 linkend="SoupSession"><type>SoupSession</type></link>. The session object
21 encapsulates all of the state that <application>libsoup</application>
22 is keeping on behalf of your program; cached HTTP connections,
23 authentication information, etc.
27 There are two subclasses of <link
28 linkend="SoupSession"><type>SoupSession</type></link> that you can use, with
29 slightly different behavior:
34 <link linkend="SoupSessionAsync"><type>SoupSessionAsync</type></link>,
35 which uses callbacks and the glib main loop to provide
40 <link linkend="SoupSessionSync"><type>SoupSessionSync</type></link>,
41 which uses blocking I/O rather than callbacks, making it more
42 suitable for threaded applications.
47 If you want to do a mix of mainloop-based and blocking I/O, you will
48 need to create two different session objects.
52 When you create the session (with <link
53 linkend="soup-session-async-new-with-options"><function>soup_session_async_new_with_options</function></link>
55 linkend="soup-session-sync-new-with-options"><function>soup_session_sync_new_with_options</function></link>),
56 you can specify various additional options:
61 <term><link linkend="SOUP-SESSION-MAX-CONNS--CAPS"><literal>SOUP_SESSION_MAX_CONNS</literal></link></term>
63 Allows you to set the maximum total number of connections
64 the session will have open at one time. (Once it reaches
65 this limit, it will either close idle connections, or
66 wait for existing connections to free up before starting
71 <term><link linkend="SOUP-SESSION-MAX-CONNS-PER-HOST--CAPS"><literal>SOUP_SESSION_MAX_CONNS_PER_HOST</literal></link></term>
73 Allows you to set the maximum total number of connections
74 the session will have open <emphasis>to a single
75 host</emphasis> at one time.
79 <term><link linkend="SOUP-SESSION-USE-NTLM--CAPS"><literal>SOUP_SESSION_USE_NTLM</literal></link></term>
81 If <literal>TRUE</literal>, then Microsoft NTLM
82 authentication will be used if available (and will be
83 preferred to HTTP Basic or Digest authentication).
84 If <literal>FALSE</literal>, NTLM authentication won't be
85 used, even if it's the only authentication type available.
86 (NTLM works differently from the standard HTTP
87 authentication types, so it needs to be handled
92 <term><link linkend="SOUP-SESSION-SSL-CA-FILE--CAPS"><literal>SOUP_SESSION_SSL_CA_FILE</literal></link></term>
94 Points to a file containing certificates for recognized
95 SSL Certificate Authorities. If this is set, then HTTPS
96 connections will be checked against these authorities, and
97 rejected if they can't be verified. (Otherwise all SSL
98 certificates will be accepted automatically.)
102 <term><link linkend="SOUP-SESSION-ASYNC-CONTEXT--CAPS"><literal>SOUP_SESSION_ASYNC_CONTEXT</literal></link></term>
105 linkend="GMainContext"><type>GMainContext</type></link>
106 which the session will use for asynchronous operations.
107 This can be set if you want to use a
108 <type>SoupSessionAsync</type> in a thread other than the
113 <term><link linkend="SOUP-SESSION-ADD-FEATURE--CAPS"><literal>SOUP_SESSION_ADD_FEATURE</literal></link> and <link linkend="SOUP-SESSION-ADD-FEATURE-BY-TYPE--CAPS"><literal>SOUP_SESSION_ADD_FEATURE_BY_TYPE</literal></link></term>
115 These allow you to specify <link
116 linkend="SoupSessionFeature"><type>SoupSessionFeature</type></link>s
117 (discussed <link linkend="session-features">below</link>)
118 to add at construct-time.
124 If you don't need to specify any options, you can just use <link
125 linkend="soup-session-async-new"><function>soup_session_async_new</function></link> or
126 <link linkend="soup-session-sync-new"><function>soup_session_sync_new</function></link>,
127 which take no arguments.
132 <refsect2 id="session-features">
133 <title>Session features</title>
136 Additional session functionality is provided as <link
137 linkend="SoupSessionFeature"><type>SoupSessionFeature</type></link>s,
138 which can be added to a session, via the <link
139 linkend="SOUP-SESSION-ADD-FEATURE--CAPS"><literal>SOUP_SESSION_ADD_FEATURE</literal></link>
141 linkend="SOUP-SESSION-ADD-FEATURE-BY-TYPE--CAPS"><literal>SOUP_SESSION_ADD_FEATURE_BY_TYPE</literal></link>
142 options at session-construction-time, or afterward via the <link
143 linkend="soup-session-add-feature"><function>soup_session_add_feature</function></link>
145 linkend="soup-session-add-feature-by-type"><function>soup_session_add_feature_by_type</function></link>
146 functions. Some of the features available in
147 <application>libsoup</application> are:
152 <term><link linkend="SoupLogger"><type>SoupLogger</type></link></term>
154 A debugging aid, which logs all of libsoup's HTTP traffic
155 to <literal>stdout</literal> (or another place you specify).
159 <term><link linkend="SoupCookieJar"><type>SoupCookieJar</type></link> and <link linkend="SoupCookieJarText"><type>SoupCookieJarText</type></link></term>
161 Support for HTTP cookies. <type>SoupCookieJar</type>
162 provides non-persistent cookie storage, while
163 <type>SoupCookieJarText</type> uses a text file to keep
164 track of cookies between sessions.
170 And in <application>libsoup-gnome</application>:
175 <term><link linkend="SOUP-TYPE-PROXY-RESOLVER-GNOME--CAPS"><type>SoupProxyResolverGNOME</type></link></term>
177 A feature that automatically determines the correct HTTP
178 proxy to use for requests.
182 <term><link linkend="SoupCookieJarSqlite"><type>SoupCookieJarSqlite</type></link></term>
184 Support for HTTP cookies stored in an
185 <application>SQLite</application> database.
191 Use the "add_feature_by_type" property/function to add features that
192 don't require any configuration (such as <link
193 linkend="SOUP-TYPE-PROXY-RESOLVER-GNOME--CAPS"><type>SoupProxyResolverGNOME</type></link>),
194 and the "add_feature" property/function to add features that must be
195 constructed first (such as <link
196 linkend="SoupLogger"><type>SoupLogger</type></link>). For example, an
197 application might do something like the following:
200 <informalexample><programlisting>
201 session = soup_session_async_new_with_options (
202 #ifdef HAVE_LIBSOUP_GNOME
203 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_GNOME,
209 logger = soup_logger_new (debug_level, -1);
210 soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));
211 g_object_unref (logger);
213 </programlisting></informalexample>
218 <title>Creating and Sending SoupMessages</title>
221 Once you have a session, you do HTTP traffic using <link
222 linkend="SoupMessage"><type>SoupMessage</type></link>. In the simplest
223 case, you only need to create the message and it's ready to send:
226 <informalexample><programlisting>
229 msg = soup_message_new ("GET", "http://example.com/");
230 </programlisting></informalexample>
233 In more complicated cases, you can use various <link
234 linkend="SoupMessage">SoupMessage</link>, <link
235 linkend="SoupMessageHeaders">SoupMessageHeaders</link>, and <link
236 linkend="SoupMessageBody">SoupMessageBody</link> methods to set the
237 request headers and body of the message:
240 <informalexample><programlisting>
243 msg = soup_message_new ("POST", "http://example.com/form.cgi");
244 soup_message_set_request (msg, "application/x-www-form-urlencoded",
245 SOUP_MEMORY_COPY, formdata, strlen (formdata));
246 soup_message_headers_append (msg->request_headers, "Referer", referring_url);
247 </programlisting></informalexample>
250 (Although this is a bad example, because
251 <application>libsoup</application> actually has convenience methods
252 for dealing with <link linkend="libsoup-24-HTML-Form-Support">HTML
253 forms</link>, as well as <link
254 linkend="libsoup-24-XMLRPC-Support">XML-RPC</link>.)
258 You can also use <link
259 linkend="soup-message-set-flags"><function>soup_message_set_flags</function></link>
260 to change some default behaviors. For example, by default,
261 <type>SoupSession</type> automatically handles responses from the
262 server that redirect to another URL. If you would like to handle these
263 yourself, you can set the <link linkend="SOUP-MESSAGE-NO-REDIRECT--CAPS"><literal>SOUP_MESSAGE_NO_REDIRECT</literal></link>
268 <title>Sending a Message Synchronously</title>
271 To send a message and wait for the response, use <link
272 linkend="soup-session-send-message"><function>soup_session_send_message</function></link>:
275 <informalexample><programlisting>
278 status = soup_session_send_message (session, msg);
279 </programlisting></informalexample>
282 (If you use <function>soup_session_send_message</function> with a
283 <link linkend="SoupSessionAsync"><type>SoupSessionAsync</type></link>,
284 it will run the main loop itself until the message is complete.)
288 The return value from <function>soup_session_send_message</function>
289 is a <link linkend="soup-status">libsoup status code</link>,
290 indicating either a transport error that prevented the message from
291 being sent, or the HTTP status that was returned by the server in
292 response to the message. (The status is also available as
293 <literal>msg->status_code</literal>.)
299 <title>Sending a Message Asynchronously</title>
302 To send a message asynchronously, use <link
303 linkend="soup-session-queue-message"><function>soup_session_queue_message</function></link>:
306 <informalexample><programlisting>
308 soup_session_queue_message (session, msg, my_callback, my_callback_data);
313 my_callback (SoupSession *session, SoupMessage *msg, gpointer user_data)
315 /* Handle the response here */
317 </programlisting></informalexample>
320 The message will be added to the session's queue, and eventually (when
321 control is returned back to the main loop), it will be sent and the
322 response be will be read. When the message is complete,
323 <literal>callback</literal> will be invoked, along with the data you
324 passed to <function>soup_session_queue_message</function>.
329 linkend="soup-session-queue-message"><function>soup_session_queue_message</function></link>
330 steals a reference to the message object, and unrefs it after the last
331 callback is invoked on it. So in the usual case, messages sent
332 asynchronously will be automatically freed for you without you needing
333 to do anything. (Of course, this wouldn't work when using the synchronous
334 API, since you will usually need continue working with the message
336 linkend="soup-session-send-message"><function>soup_session_send_message</function></link>,
337 so in that case, you must unref it explicitly when you are done with
343 linkend="soup-session-queue-message"><function>soup_session_queue_message</function></link>
345 linkend="SoupSessionSync"><type>SoupSessionSync</type></link>, the
346 message will be sent in another thread, with the callback eventually
347 being invoked in the session's <link linkend="SOUP-SESSION-ASYNC-CONTEXT--CAPS"><literal>SOUP_SESSION_ASYNC_CONTEXT</literal></link>.)
355 <title>Processing the Response</title>
358 Once you have received the response from the server, synchronously or
359 asynchronously, you can look at the response fields in the
360 <literal>SoupMessage</literal> to decide what to do next. The
361 <structfield>status_code</structfield> and
362 <structfield>reason_phrase</structfield> fields contain the numeric
363 status and textual status response from the server.
364 <structfield>response_headers</structfield> contains the response
365 headers, which you can investigate using <link
366 linkend="soup-message-headers-get"><function>soup_message_headers_get</function></link> and
368 linkend="soup-message-headers-foreach"><function>soup_message_headers_foreach</function></link>.
369 The response body (if any) is in the
370 <structfield>response_body</structfield> field.
375 linkend="SoupMessageHeaders"><type>SoupMessageHeaders</type></link>
376 automatically parses several important headers in
377 <structfield>response_headers</structfield> for you and provides
378 specialized accessors for them. Eg, <link
379 linkend="soup-message-headers-get-content-type"><function>soup_message_headers_get_content_type</function></link>.
380 There are several generic methods such as <link
381 linkend="soup-header-parse-param-list"><function>soup_header_parse_param_list</function></link>
382 (for parsing an attribute-list-type header) and <link
383 linkend="soup-header-contains"><function>soup_header_contains</function></link>
384 (for quickly testing if a list-type header contains a particular
385 token). These handle the various syntactical oddities of parsing HTTP
386 headers much better than functions like
387 <function>g_strsplit</function> or <function>strstr</function>.
393 <title>Intermediate/Automatic Processing</title>
396 You can also connect to various <type>SoupMessage</type> signals to do
397 processing at intermediate stages of HTTP I/O. Eg, the <link
398 linkend="SoupMessage-got-chunk"><literal>got-chunk</literal></link>
399 signal is emitted as each piece of the response body is read (allowing
400 you to provide progress information when receiving a large response,
401 for example). <type>SoupMessage</type> also provides two convenience
403 linkend="soup-message-add-header-handler"><function>soup_message_add_header_handler</function></link>,
405 linkend="soup-message-add-status-code-handler"><function>soup_message_add_status_code_handler</function></link>,
406 which allow you to set up a signal handler that will only be invoked
407 for messages with certain response headers or status codes.
408 <type>SoupSession</type> uses this internally to handle authentication
413 When using the synchronous API, the callbacks and signal handlers will
414 be invoked during the call to <link
415 linkend="soup-session-send-message"><function>soup_session_send_message</function></link>.
419 To automatically set up handlers on all messages sent via a session,
420 you can connect to the session's <link
421 linkend="SoupSession-request-started"><literal>request_started</literal></link>
422 signal, and add handlers to each message from there.
428 <title>Handling Authentication</title>
431 <type>SoupSession</type> handles most of the details of HTTP
432 authentication for you. If it receives a 401 ("Unauthorized") or 407
433 ("Proxy Authentication Required") response, the session will emit the
434 <link linkend="SoupSession-authenticate">authenticate</link> signal,
435 providing you with a <link
436 linkend="SoupAuth"><type>SoupAuth</type></link> object indicating the
437 authentication type ("Basic", "Digest", or "NTLM") and the realm name
438 provided by the server. If you have a username and password available
439 (or can generate one), call <link
440 linkend="soup-auth-authenticate"><function>soup_auth_authenticate</function></link>
441 to give the information to libsoup. The session will automatically
442 requeue the message and try it again with that authentication
443 information. (If you don't call
444 <function>soup_auth_authenticate</function>, the session will just
445 return the message to the application with its 401 or 407 status.)
449 If the server doesn't accept the username and password provided, the
450 session will emit <link
451 linkend="SoupSession-authenticate">authenticate</link> again, with the
452 <literal>retrying</literal> parameter set to <literal>TRUE</literal>. This lets the
453 application know that the information it provided earlier was
454 incorrect, and gives it a chance to try again. If this
455 username/password pair also doesn't work, the session will contine to
456 emit <literal>authenticate</literal> again and again until the
457 provided username/password successfully authenticates, or until the
458 signal handler fails to call <link
459 linkend="soup-auth-authenticate"><function>soup_auth_authenticate</function></link>,
460 at which point <application>libsoup</application> will allow the
461 message to fail (with status 401 or 407).
465 If you need to handle authentication asynchronously (eg, to pop up a
466 password dialog without recursively entering the main loop), you can
467 do that as well. Just call <link
468 linkend="soup-session-pause-message"><function>soup_session_pause_message</function></link>
469 on the message before returning from the signal handler, and
470 <function>g_object_ref</function> the <type>SoupAuth</type>. Then,
471 later on, after calling <function>soup_auth_authenticate</function>
472 (or deciding not to), call <link
473 linkend="soup-session-unpause-message"><function>soup_session_unpause_message</function></link>
474 to resume the paused message.
480 <title>Multi-threaded usage</title>
483 The only explicitly thread-safe operations in
484 <application>libsoup</application> are <link
485 linkend="SoupSessionSync"><type>SoupSessionSync</type></link>'s
486 implementations of the <link
487 linkend="SoupSession"><type>SoupSession</type></link> methods. So
488 after creating a <type>SoupSessionSync</type>, you can call <link
489 linkend="soup-session-send-message"><function>soup_session_send_message</function></link>
491 linkend="soup-session-cancel-message"><function>soup_session_cancel_message</function></link>
492 on it from any thread. But, eg, while the session is processing a
493 message, you should not call any <link
494 linkend="SoupMessage"><type>SoupMessage</type></link> methods on it
495 from any thread other than the one in which it is being sent. (That
496 is, you should not call any <type>SoupMessage</type> methods on it
497 except from a message or session callback or signal handler.)
501 All other objects (including <link
502 linkend="SoupSessionAsync"><type>SoupSessionAsync</type></link>)
503 should only be used from a single thread, with objects that are also
504 only be used from that thread. (And in particular, if you set a
506 linkend="GMainContext"><type>GMainContext</type></link> on a session,
507 socket, etc, then you can only use that object from the thread in
508 which that <type>GMainContext</type> is running.)
514 <title>Sample Programs</title>
517 A few sample programs are available in the
518 <application>libsoup</application> sources:
523 <emphasis role="bold"><literal>get</literal></emphasis> is a simple command-line
524 HTTP GET utility using the asynchronous API.
528 <emphasis role="bold"><literal>getbug</literal></emphasis> is a trivial
529 demonstration of the <link
530 linkend="libsoup-XMLRPC-Support">XMLRPC</link> interface.
532 role="bold"><literal>xmlrpc-test</literal></emphasis> provides
533 a slightly more complicated example.)
537 <emphasis role="bold"><literal>auth-test</literal></emphasis> shows how to use
538 authentication handlers and status-code handlers, although in
539 a fairly unusual way.
543 <emphasis role="bold"><literal>simple-proxy</literal></emphasis> uses both the
544 client and server APIs to create a simple (and not very
545 RFC-compliant) proxy server. It shows how to use the <link
546 linkend="SoupMessageFlags"><literal>SOUP_MESSAGE_OVERWRITE_CHUNKS</literal></link>
547 flag when reading a message to save memory by processing each
548 chunk of the message as it is read, rather than accumulating
549 them all into a single buffer to process all at the end.
554 More complicated examples are available in GNOME CVS. The <ulink
555 url="http://live.gnome.org/LibSoup"><application>libsoup</application>
556 pages</ulink> on the GNOME wiki include a <ulink
557 url="http://live.gnome.org/LibSoup/Users">list of applications using
558 <application>libsoup</application></ulink>.