1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
Title: Advanced Usage
Slug: client-advanced
# Advanced Usage
## Customizing Session Options
When you create the session with [ctor@Session.new_with_options], you can
specify various additional options. See the [class@Session] documentation for
more details but these may be interesting: [property@Session:max-conns] and
[property@Session:max-conns-per-host], [property@Session:user-agent],
[property@Session:timeout], [property@Session:accept-language] and
[property@Session:accept-language-auto].
## Adding Session Features
Additional session functionality is provided as [iface@SessionFeature]s, which
can be added to or removed from a session.
One such feature is [class@ContentDecoder] which is added by default. This
advertises to servers that the client supports compression, and automatically
decompresses compressed responses.
Some other available features that you can add include:
<table>
<tr>
<td>[class@Logger]</td>
<td>
A debugging aid, which logs all of libsoup's HTTP traffic
to <code>stdout</code> (or another place you specify).
</td>
</tr>
<tr>
<td>
[class@CookieJar], [class@CookieJarText],
and [class@CookieJarDB].
</td>
<td>
Support for HTTP cookies. [class@CookieJar]
provides non-persistent cookie storage, while
[class@CookieJarText] uses a text file to keep
track of cookies between sessions, and
[class@CookieJarDB] uses a
<tt>SQLite</tt> database.
</td>
</tr>
<tr>
<td>[class@ContentSniffer]</td>
<td>
Uses the HTML5 sniffing rules to attempt to
determine the Content-Type of a response when the
server does not identify the Content-Type, or appears to
have provided an incorrect one.
</td>
</tr>
</table>
Use the [method@Session.add_feature_by_type] function to add features that don't
require any configuration (such as [class@ContentSniffer]), and the
[method@Session.add_feature]function to add features that must be constructed
first (such as [class@Logger]). For example, an application might do something
like the following:
```c
session = soup_session_new ();
soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
if (debug_level) {
SoupLogger *logger = soup_logger_new (debug_level);
soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));
g_object_unref (logger);
}
```
You can also remove features by calling [method@Session.remove_feature] or
[method@Session.remove_feature_by_type].
## Using a proxy
By default libsoup tries to respect the default proxy (as best as
[func@Gio.ProxyResolver.get_default] knows), however you can set a custom one or
disable it outright using the [property@Session:proxy-resolver] property. For
example:
```c
{
GProxyResolver *resolver = g_simple_proxy_resolver_new ("https://my-proxy-example.org", NULL);
SoupSession *session = soup_session_new_with_options ("proxy-resolver", resolver, NULL);
g_object_unref (resolver);
}
```
## Using the SoupMessage API
The [class@Message] type contains all the state for a request and response pair
that you send and receive to a server. For many more complex tasks you will have
to create one of these and send it with the [method@Session.send] function. For
example this sends a request with the `HEAD` method:
```c
{
SoupSession *session = soup_session_new ();
SoupMessage *msg = soup_message_new (SOUP_METHOD_HEAD, "https://example.org");
// This allows you to also customize the request headers:
SoupMessageHeaders *request_headers = soup_message_get_request_headers (msg);
soup_message_headers_replace (request_headers, "Foo", "Bar");
GInputStream *in_stream = soup_session_send (session, msg, NULL, NULL);
if (in_stream) {
g_print ("Message was sent and recived a response of %u (%s)\n",
soup_message_get_status (msg), soup_message_get_reason_phrase (msg));
// You can also inspect the response headers via soup_message_get_response_headers();
g_object_unref (in_stream);
}
g_object_unref (msg);
g_object_unref (session);
}
```
## Handling authentication
```c
static gboolean
authenticate_callback (SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer user_data)
{
if (retrying) {
// Maybe don't try again if our password failed
return FALSE;
}
soup_auth_authenticate (auth, "username", "password");
// Returning TRUE means we have or *will* handle it.
// soup_auth_authenticate() or soup_auth_cancel() can be called later
// for example after showing a prompt to the user or loading the password
// from a keyring.
return TRUE;
}
int main (int argc, char **argv)
{
SoupSession *session = soup_session_new ();
SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "https://example.org");
g_signal_connect (msg, "authenticate", G_CALLBACK (authenticate_callback), NULL);
GInputStream *in_stream = soup_session_send (session, msg, NULL, NULL);
if (in_stream) {
g_object_unref (in_stream);
}
return 0;
}
```
|