summaryrefslogtreecommitdiff
path: root/docs/reference/client-advanced.md
blob: e7bc1045904e42b6404e8670f305f07284c70838 (plain)
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: Advances 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;
}
```