summaryrefslogtreecommitdiff
path: root/docs/reference/html/libsoup-server-howto.html
blob: 80d4649daf54602bed2c3c05533653411aade615 (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>libsoup Server Basics: libsoup Reference Manual</title>
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="index.html" title="libsoup Reference Manual">
<link rel="up" href="ch01.html" title="Tutorial">
<link rel="prev" href="libsoup-session-porting.html" title="Porting to the new SoupSession">
<link rel="next" href="ch02.html" title="Core API">
<meta name="generator" content="GTK-Doc V1.28.1 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
<td width="100%" align="left" class="shortcuts"></td>
<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
<td><a accesskey="u" href="ch01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
<td><a accesskey="p" href="libsoup-session-porting.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
<td><a accesskey="n" href="ch02.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
</tr></table>
<div class="refentry">
<a name="libsoup-server-howto"></a><div class="titlepage"></div>
<div class="refnamediv"><table width="100%"><tr>
<td valign="top">
<h2><span class="refentrytitle">libsoup Server Basics</span></h2>
<p>libsoup Server Basics — Server-side tutorial</p>
</td>
<td class="gallery_image" valign="top" align="right"></td>
</tr></table></div>
<div class="refsect2">
<a name="id-1.2.6.3"></a><h3>Creating a SoupServer</h3>
<p>
As with the client API, there is a single object that will encapsulate
most of your interactions with libsoup. In this case, <a class="link" href="SoupServer.html" title="SoupServer"><span class="type">SoupServer</span></a>.
</p>
<p>
You create the server with <a class="link" href="SoupServer.html#soup-server-new" title="soup_server_new ()"><code class="function">soup_server_new</code></a>,
and as with the <span class="type">SoupSession</span> constructor, you can specify
a few additional options:
</p>
<div class="variablelist"><table border="0" class="variablelist">
<colgroup>
<col align="left" valign="top">
<col>
</colgroup>
<tbody>
<tr>
<td><p><span class="term"><a class="link" href="SoupServer.html#SOUP-SERVER-TLS-CERTIFICATE:CAPS" title="SOUP_SERVER_TLS_CERTIFICATE"><code class="literal">SOUP_SERVER_TLS_CERTIFICATE</code></a></span></p></td>
<td><p>
	    A <span class="type">GTlsCertificate</span>
	    (containing a private key) that will be used when handling
	    HTTPS requests on the server.
	</p></td>
</tr>
<tr>
<td><p><span class="term"><a class="link" href="SoupServer.html#SOUP-SERVER-RAW-PATHS:CAPS" title="SOUP_SERVER_RAW_PATHS"><code class="literal">SOUP_SERVER_RAW_PATHS</code></a></span></p></td>
<td><p>
	    Set this to <code class="literal">TRUE</code> if you don't want
	    <span class="application">libsoup</span> to decode %-encoding
	    in the Request-URI. (Eg, because you need to treat
	    <code class="literal">"/foo/bar"</code> and
	    <code class="literal">"/foo%2Fbar"</code> as different paths.
	</p></td>
</tr>
<tr>
<td><p><span class="term"><a class="link" href="SoupServer.html#SOUP-SERVER-SERVER-HEADER:CAPS" title="SOUP_SERVER_SERVER_HEADER"><code class="literal">SOUP_SERVER_SERVER_HEADER</code></a></span></p></td>
<td><p>
	    Allows you to set a Server header string that will be sent
	    on all responses.
	</p></td>
</tr>
<tr>
<td><p><span class="term"><a class="link" href="SoupServer.html#SOUP-SERVER-HTTP-ALIASES:CAPS" title="SOUP_SERVER_HTTP_ALIASES"><code class="literal">SOUP_SERVER_HTTP_ALIASES</code></a>
	and <a class="link" href="SoupServer.html#SOUP-SERVER-HTTPS-ALIASES:CAPS" title="SOUP_SERVER_HTTPS_ALIASES"><code class="literal">SOUP_SERVER_HTTPS_ALIASES</code></a></span></p></td>
<td><p>
	    Allow you to tell the server to recognize additional URI
	    schemes as aliases for "<code class="literal">http</code>" or
	    <code class="literal">https</code>. You can set this if you are
	    serving URIs with schemes like "<code class="literal">dav</code>" or
	    "<code class="literal">webcal</code>".
	</p></td>
</tr>
</tbody>
</table></div>
</div>
<hr>
<div class="refsect2">
<a name="id-1.2.6.4"></a><h3>Adding Listening Sockets</h3>
<p>
  To tell the server where to listen, call <a class="link" href="SoupServer.html#soup-server-listen" title="soup_server_listen ()"><code class="function">soup_server_listen</code></a>
  (to listen on a specific <span class="type">GSocketAddress</span>), <a class="link" href="SoupServer.html#soup-server-listen-all" title="soup_server_listen_all ()"><code class="function">soup_server_listen_all</code></a>
  (to listen on a given port on all network interfaces), or <a class="link" href="SoupServer.html#soup-server-listen-local" title="soup_server_listen_local ()"><code class="function">soup_server_listen_local</code></a>
  (to listen to a given port on the loopback interface only). You can
  call any of these functions multiple times, to set up multiple
  listening sockets.
</p>
<p>
  To set up an HTTPS server, you must first either set the <a class="link" href="SoupServer.html#SOUP-SERVER-TLS-CERTIFICATE:CAPS" title="SOUP_SERVER_TLS_CERTIFICATE"><code class="literal">SOUP_SERVER_TLS_CERTIFICATE</code></a>
  property, or else call <a class="link" href="SoupServer.html#soup-server-set-ssl-cert-file" title="soup_server_set_ssl_cert_file ()"><code class="function">soup_server_set_ssl_cert_file</code></a>.
  After that you can pass the <a class="link" href="SoupServer.html#SOUP-SERVER-LISTEN-HTTPS:CAPS"><code class="literal">SOUP_SERVER_LISTEN_HTTPS</code></a>
  option to <a class="link" href="SoupServer.html#soup-server-listen" title="soup_server_listen ()"><code class="function">soup_server_listen</code></a>,
  etc.
</p>
<p>
  By default, servers listen for both IPv4 and IPv6 connections; if
  you don't want this, use the <a class="link" href="SoupServer.html#SOUP-SERVER-LISTEN-IPV4-ONLY:CAPS"><code class="literal">SOUP_SERVER_LISTEN_IPV4_ONLY</code></a>
  or <a class="link" href="SoupServer.html#SOUP-SERVER-LISTEN-IPV6-ONLY:CAPS"><code class="literal">SOUP_SERVER_LISTEN_IPV6_ONLY</code></a>
  options.
</p>
<p>
  The server runs asynchronously, in the thread-default
  <span class="type">GMainContext</span> of the
  thread in which the "listen" calls were made.
</p>
</div>
<hr>
<div class="refsect2">
<a name="soup-server-old-api"></a><h3>The Old SoupServer Listening API</h3>
<p>
<a class="link" href="SoupServer.html#soup-server-listen" title="soup_server_listen ()"><code class="function">soup_server_listen</code></a>,
etc, are available only in <span class="application">libsoup</span> 2.46 and
later. In earlier versions, there was a simpler API, in which a server
could only listen on a single port, determined at construct time
either by passing the <a class="link" href="libsoup-2.4-SoupServer-deprecated-API.html#SOUP-SERVER-INTERFACE:CAPS" title="SOUP_SERVER_INTERFACE"><code class="literal">SOUP_SERVER_INTERFACE</code></a>
property (to specify a <a class="link" href="SoupAddress.html" title="SoupAddress"><span class="type">SoupAddress</span></a> to listen on),
or the <a class="link" href="libsoup-2.4-SoupServer-deprecated-API.html#SOUP-SERVER-PORT:CAPS" title="SOUP_SERVER_PORT"><code class="literal">SOUP_SERVER_PORT</code></a>
property (to specify a port to listen on, on all interfaces). The <a class="link" href="libsoup-2.4-SoupServer-deprecated-API.html#SOUP-SERVER-SSL-CERT-FILE:CAPS" title="SOUP_SERVER_SSL_CERT_FILE"><code class="literal">SOUP_SERVER_SSL_CERT_FILE</code></a>
and <a class="link" href="libsoup-2.4-SoupServer-deprecated-API.html#SOUP-SERVER-SSL-KEY-FILE:CAPS" title="SOUP_SERVER_SSL_KEY_FILE"><code class="literal">SOUP_SERVER_SSL_KEY_FILE</code></a>
properties could be used to create an HTTP server.
</p>
<p>
When using this API, if <a class="link" href="SoupServer.html" title="SoupServer"><span class="type">SoupServer</span></a> is unable to bind
the listening socket, or unable to read the provided certificate or
key files, then it will return <code class="literal">NULL</code> from its
constructor (with no further indication of what exactly went wrong).
</p>
<p>
Additionally, when using this API, it is necessary to call <a class="link" href="libsoup-2.4-SoupServer-deprecated-API.html#soup-server-run" title="soup_server_run ()"><code class="function">soup_server_run</code></a>
or <a class="link" href="libsoup-2.4-SoupServer-deprecated-API.html#soup-server-run-async" title="soup_server_run_async ()"><code class="function">soup_server_run_async</code></a>
to start the server after creating it.
</p>
</div>
<hr>
<div class="refsect2">
<a name="id-1.2.6.6"></a><h3>Adding Handlers</h3>
<p>
By default, <a class="link" href="SoupServer.html" title="SoupServer"><span class="type">SoupServer</span></a>
returns "404 Not Found" in response to all requests (except ones that
it can't parse, which get "400 Bad Request"). To override this
behavior, call <a class="link" href="SoupServer.html#soup-server-add-handler" title="soup_server_add_handler ()"><code class="function">soup_server_add_handler</code></a>
to set a callback to handle certain URI paths.
</p>
<div class="informalexample">
  <table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
    <tbody>
      <tr>
        <td class="listing_lines" align="right"><pre>1
2</pre></td>
        <td class="listing_code"><pre class="programlisting"><span class="function"><a href="SoupServer.html#soup-server-add-handler">soup_server_add_handler</a></span> <span class="gtkdoc opt">(</span>server<span class="gtkdoc opt">,</span> <span class="string">&quot;/foo&quot;</span><span class="gtkdoc opt">,</span> server_callback<span class="gtkdoc opt">,</span>
                         data<span class="gtkdoc opt">,</span> destroy_notify<span class="gtkdoc opt">);</span></pre></td>
      </tr>
    </tbody>
  </table>
</div>

<p>
The <code class="literal">"/foo"</code> indicates the base path for this
handler. When a request comes in, if there is a handler registered for
exactly the path in the request's <code class="literal">Request-URI</code>, then
that handler will be called. Otherwise
<span class="application">libsoup</span> will strip path components one by
one until it finds a matching handler. So for example, a request of
the form
"<code class="literal">GET /foo/bar/baz.html?a=1&amp;b=2 HTTP/1.1</code>"
would look for handlers for "<code class="literal">/foo/bar/baz.html</code>",
"<code class="literal">/foo/bar</code>", and "<code class="literal">/foo</code>". If a
handler has been registered with a <code class="literal">NULL</code> base path,
then it is used as the default handler for any request that doesn't
match any other handler.
</p>
</div>
<hr>
<div class="refsect2">
<a name="id-1.2.6.7"></a><h3>Responding to Requests</h3>
<p>
A handler callback looks something like this:
</p>
<div class="informalexample">
  <table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
    <tbody>
      <tr>
        <td class="listing_lines" align="right"><pre>1
2
3
4
5
6
7
8
9
10</pre></td>
        <td class="listing_code"><pre class="programlisting"><span class="gtkdoc kwb">static void</span>
<span class="function">server_callback</span> <span class="gtkdoc opt">(</span>SoupServer        <span class="gtkdoc opt">*</span>server<span class="gtkdoc opt">,</span>
                 SoupMessage       <span class="gtkdoc opt">*</span>msg<span class="gtkdoc opt">,</span> 
                 <span class="gtkdoc kwb">const char</span>        <span class="gtkdoc opt">*</span>path<span class="gtkdoc opt">,</span>
                 GHashTable        <span class="gtkdoc opt">*</span>query<span class="gtkdoc opt">,</span>
                 SoupClientContext <span class="gtkdoc opt">*</span>client<span class="gtkdoc opt">,</span>
                 gpointer           user_data<span class="gtkdoc opt">)</span>
<span class="gtkdoc opt">{</span>
	<span class="gtkdoc opt">...</span>
<span class="gtkdoc opt">}</span></pre></td>
      </tr>
    </tbody>
  </table>
</div>

<p>
<code class="literal">msg</code> is the request that has been received and
<code class="literal">user_data</code> is the data that was passed to <a class="link" href="SoupServer.html#soup-server-add-handler" title="soup_server_add_handler ()"><code class="function">soup_server_add_handler</code></a>.
<code class="literal">path</code> is the path (from <code class="literal">msg</code>'s
URI), and <code class="literal">query</code> contains the result of parsing the
URI query field. (It is <code class="literal">NULL</code> if there was no
query.) <code class="literal">client</code> is a <a class="link" href="SoupServer.html#SoupClientContext"><span class="type">SoupClientContext</span></a>,
which contains additional information about the client (including its
IP address, and whether or not it used HTTP authentication).
</p>
<p>
By default, <span class="application">libsoup</span> assumes that you have
completely finished processing the message when you return from the
callback, and that it can therefore begin sending the response. If you
are not ready to send a response immediately (eg, you have to contact
another server, or wait for data from a database), you must call <a class="link" href="SoupServer.html#soup-server-pause-message" title="soup_server_pause_message ()"><code class="function">soup_server_pause_message</code></a>
on the message before returning from the callback. This will delay
sending a response until you call <a class="link" href="SoupServer.html#soup-server-unpause-message" title="soup_server_unpause_message ()"><code class="function">soup_server_unpause_message</code></a>.
(You must also connect to the <a class="link" href="SoupMessage.html#SoupMessage-finished" title="The “finished” signal">finished</a> signal on the message
in this case, so that you can break off processing if the client
unexpectedly disconnects before you start sending the data.)
</p>
<p>
To set the response status, call <a class="link" href="SoupMessage.html#soup-message-set-status" title="soup_message_set_status ()"><code class="function">soup_message_set_status</code></a>
or <a class="link" href="SoupMessage.html#soup-message-set-status-full" title="soup_message_set_status_full ()"><code class="function">soup_message_set_status_full</code></a>.
If the response requires a body, you must decide whether to use
<code class="literal">Content-Length</code> encoding (the default), or
<code class="literal">chunked</code> encoding.
</p>
<div class="refsect3">
<a name="id-1.2.6.7.7"></a><h4>Responding with <code class="literal">Content-Length</code>
Encoding</h4>
<p>
This is the simpler way to set a response body, if you have all of the
data available at once.
</p>
<div class="informalexample">
  <table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
    <tbody>
      <tr>
        <td class="listing_lines" align="right"><pre>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</pre></td>
        <td class="listing_code"><pre class="programlisting"><span class="gtkdoc kwb">static void</span>
<span class="function">server_callback</span> <span class="gtkdoc opt">(</span>SoupServer        <span class="gtkdoc opt">*</span>server<span class="gtkdoc opt">,</span>
                 SoupMessage       <span class="gtkdoc opt">*</span>msg<span class="gtkdoc opt">,</span> 
                 <span class="gtkdoc kwb">const char</span>        <span class="gtkdoc opt">*</span>path<span class="gtkdoc opt">,</span>
                 GHashTable        <span class="gtkdoc opt">*</span>query<span class="gtkdoc opt">,</span>
                 SoupClientContext <span class="gtkdoc opt">*</span>client<span class="gtkdoc opt">,</span>
                 gpointer           user_data<span class="gtkdoc opt">)</span>
<span class="gtkdoc opt">{</span>
	MyServerData <span class="gtkdoc opt">*</span>server_data <span class="gtkdoc opt">=</span> user_data<span class="gtkdoc opt">;</span>
	<span class="gtkdoc kwb">const char</span> <span class="gtkdoc opt">*</span>mime_type<span class="gtkdoc opt">;</span>
	GByteArray <span class="gtkdoc opt">*</span>body<span class="gtkdoc opt">;</span>

	<span class="keyword">if</span> <span class="gtkdoc opt">(</span>msg<span class="gtkdoc opt">-&gt;</span>method <span class="gtkdoc opt">!=</span> SOUP_METHOD_GET<span class="gtkdoc opt">) {</span>
		<span class="function"><a href="SoupMessage.html#soup-message-set-status">soup_message_set_status</a></span> <span class="gtkdoc opt">(</span>msg<span class="gtkdoc opt">,</span> SOUP_STATUS_NOT_IMPLEMENTED<span class="gtkdoc opt">);</span>
		<span class="keyword">return</span><span class="gtkdoc opt">;</span>
	<span class="gtkdoc opt">}</span>

	<span class="comment">/* This is somewhat silly. Presumably your server will do</span>
<span class="comment">	 * something more interesting.</span>
<span class="comment">	 */</span>
	body <span class="gtkdoc opt">=</span> <span class="function">g_hash_table_lookup</span> <span class="gtkdoc opt">(</span>server_data<span class="gtkdoc opt">-&gt;</span>bodies<span class="gtkdoc opt">,</span> path<span class="gtkdoc opt">);</span>
	mime_type <span class="gtkdoc opt">=</span> <span class="function">g_hash_table_lookup</span> <span class="gtkdoc opt">(</span>server_data<span class="gtkdoc opt">-&gt;</span>mime_types<span class="gtkdoc opt">,</span> path<span class="gtkdoc opt">);</span>
	<span class="keyword">if</span> <span class="gtkdoc opt">(!</span>body <span class="gtkdoc opt">|| !</span>mime_type<span class="gtkdoc opt">) {</span>
		<span class="function"><a href="SoupMessage.html#soup-message-set-status">soup_message_set_status</a></span> <span class="gtkdoc opt">(</span>msg<span class="gtkdoc opt">,</span> SOUP_STATUS_NOT_FOUND<span class="gtkdoc opt">);</span>
		<span class="keyword">return</span><span class="gtkdoc opt">;</span>
	<span class="gtkdoc opt">}</span>

	<span class="function"><a href="SoupMessage.html#soup-message-set-status">soup_message_set_status</a></span> <span class="gtkdoc opt">(</span>msg<span class="gtkdoc opt">,</span> SOUP_STATUS_OK<span class="gtkdoc opt">);</span>
	<span class="function"><a href="SoupMessage.html#soup-message-set-response">soup_message_set_response</a></span> <span class="gtkdoc opt">(</span>msg<span class="gtkdoc opt">,</span> mime_type<span class="gtkdoc opt">,</span> SOUP_MEMORY_COPY<span class="gtkdoc opt">,</span>
	                           body<span class="gtkdoc opt">-&gt;</span>data<span class="gtkdoc opt">,</span> body<span class="gtkdoc opt">-&gt;</span>len<span class="gtkdoc opt">);</span>
<span class="gtkdoc opt">}</span></pre></td>
      </tr>
    </tbody>
  </table>
</div>

</div>
<div class="refsect3">
<a name="id-1.2.6.7.8"></a><h4>Responding with <code class="literal">chunked</code> Encoding</h4>
<p>
If you want to supply the response body in chunks as it becomes
available, use <code class="literal">chunked</code> encoding instead. In this
case, first call <a class="link" href="SoupMessageHeaders.html#soup-message-headers-set-encoding" title="soup_message_headers_set_encoding ()"><code class="function">soup_message_headers_set_encoding</code></a> <code class="literal">(msg-&gt;response_headers, <a class="link" href="SoupMessageHeaders.html#SoupEncoding" title="enum SoupEncoding">SOUP_ENCODING_CHUNKED</a>)</code>
to tell <span class="application">libsoup</span> that you'll be using
chunked encoding. Then call <a class="link" href="SoupMessageBody.html#soup-message-body-append" title="soup_message_body_append ()"><code class="function">soup_message_body_append</code></a>
(or <a class="link" href="SoupMessageBody.html#soup-message-body-append-buffer" title="soup_message_body_append_buffer ()"><code class="function">soup_message_body_append_buffer</code></a>)
on <code class="literal">msg-&gt;response_body</code> with each chunk of the
response body as it becomes available, and call <a class="link" href="SoupMessageBody.html#soup-message-body-complete" title="soup_message_body_complete ()"><code class="function">soup_message_body_complete</code></a>
when the response is complete. After each of these calls, you must
also call <a class="link" href="SoupServer.html#soup-server-unpause-message" title="soup_server_unpause_message ()"><code class="function">soup_server_unpause_message</code></a>
to cause the chunk to be sent. (You do not normally need to call <a class="link" href="SoupServer.html#soup-server-pause-message" title="soup_server_pause_message ()"><code class="function">soup_server_pause_message</code></a>,
because I/O is automatically paused when doing a
<code class="literal">chunked</code> transfer if no chunks are available.)
</p>
<p>
When using chunked encoding, you must also connect to the <a class="link" href="SoupMessage.html#SoupMessage-finished" title="The “finished” signal">finished</a> signal on the message,
so that you will be notified if the client disconnects between two
chunks; <span class="type">SoupServer</span> will unref the message if that
happens, so you must stop adding new chunks to the response at that
point. (An alternate possibility is to write each new chunk only when
the <a class="link" href="SoupMessage.html#SoupMessage-wrote-chunk" title="The “wrote-chunk” signal">wrote_chunk</a> signal
is emitted indicating that the previous one was written successfully.)
</p>
<p>
The <span class="bold"><strong><code class="literal">simple-proxy</code></strong></span>
example in the <code class="literal">examples/</code> directory gives an example of
using <code class="literal">chunked</code> encoding.
</p>
</div>
</div>
<hr>
<div class="refsect2">
<a name="id-1.2.6.8"></a><h3>Handling Authentication</h3>
<p>
To have <a class="link" href="SoupServer.html" title="SoupServer"><span class="type">SoupServer</span></a>
handle HTTP authentication for you, create a <a class="link" href="SoupAuthDomainBasic.html" title="SoupAuthDomainBasic"><span class="type">SoupAuthDomainBasic</span></a>
or <a class="link" href="SoupAuthDomainDigest.html" title="SoupAuthDomainDigest"><span class="type">SoupAuthDomainDigest</span></a>,
and pass it to <a class="link" href="SoupServer.html#soup-server-add-auth-domain" title="soup_server_add_auth_domain ()"><code class="function">soup_server_add_auth_domain</code></a>:
</p>
<div class="informalexample">
  <table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
    <tbody>
      <tr>
        <td class="listing_lines" align="right"><pre>1
2
3
4
5
6
7
8
9
10
11</pre></td>
        <td class="listing_code"><pre class="programlisting">SoupAuthDomain <span class="gtkdoc opt">*</span>domain<span class="gtkdoc opt">;</span>

domain <span class="gtkdoc opt">=</span> <span class="function"><a href="SoupAuthDomainBasic.html#soup-auth-domain-basic-new">soup_auth_domain_basic_new</a></span> <span class="gtkdoc opt">(</span>
	SOUP_AUTH_DOMAIN_REALM<span class="gtkdoc opt">,</span> <span class="string">&quot;My Realm&quot;</span><span class="gtkdoc opt">,</span>
	SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK<span class="gtkdoc opt">,</span> auth_callback<span class="gtkdoc opt">,</span>
	SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA<span class="gtkdoc opt">,</span> auth_data<span class="gtkdoc opt">,</span>
	SOUP_AUTH_DOMAIN_ADD_PATH<span class="gtkdoc opt">,</span> <span class="string">&quot;/foo&quot;</span><span class="gtkdoc opt">,</span>
	SOUP_AUTH_DOMAIN_ADD_PATH<span class="gtkdoc opt">,</span> <span class="string">&quot;/bar/private&quot;</span><span class="gtkdoc opt">,</span>
	NULL<span class="gtkdoc opt">);</span>
<span class="function"><a href="SoupServer.html#soup-server-add-auth-domain">soup_server_add_auth_domain</a></span> <span class="gtkdoc opt">(</span>server<span class="gtkdoc opt">,</span> domain<span class="gtkdoc opt">);</span>
<span class="function">g_object_unref</span> <span class="gtkdoc opt">(</span>domain<span class="gtkdoc opt">);</span></pre></td>
      </tr>
    </tbody>
  </table>
</div>

<p>
Then, every request under one of the auth domain's paths will be
passed to the <code class="literal">auth_callback</code> first before being
passed to the <code class="literal">server_callback</code>:
</p>
<div class="informalexample">
  <table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
    <tbody>
      <tr>
        <td class="listing_lines" align="right"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</pre></td>
        <td class="listing_code"><pre class="programlisting"><span class="gtkdoc kwb">static</span> gboolean
<span class="function">auth_callback</span> <span class="gtkdoc opt">(</span>SoupAuthDomain <span class="gtkdoc opt">*</span>domain<span class="gtkdoc opt">,</span> SoupMessage <span class="gtkdoc opt">*</span>msg<span class="gtkdoc opt">,</span>
               <span class="gtkdoc kwb">const char</span> <span class="gtkdoc opt">*</span>username<span class="gtkdoc opt">,</span> <span class="gtkdoc kwb">const char</span> <span class="gtkdoc opt">*</span>password<span class="gtkdoc opt">,</span>
               gpointer user_data<span class="gtkdoc opt">)</span>
<span class="gtkdoc opt">{</span>
	MyServerData <span class="gtkdoc opt">*</span>server_data <span class="gtkdoc opt">=</span> user_data<span class="gtkdoc opt">;</span>
	MyUserData <span class="gtkdoc opt">*</span>user<span class="gtkdoc opt">;</span>

	user <span class="gtkdoc opt">=</span> <span class="function">my_server_data_lookup_user</span> <span class="gtkdoc opt">(</span>server_data<span class="gtkdoc opt">,</span> username<span class="gtkdoc opt">);</span>
	<span class="keyword">if</span> <span class="gtkdoc opt">(!</span>user<span class="gtkdoc opt">)</span>
		<span class="keyword">return</span> FALSE<span class="gtkdoc opt">;</span>

	<span class="comment">/* FIXME: Don&apos;t do this. Keeping a cleartext password database</span>
<span class="comment">	 * is bad.</span>
<span class="comment">	 */</span>
	<span class="keyword">return</span> <span class="function">strcmp</span> <span class="gtkdoc opt">(</span>password<span class="gtkdoc opt">,</span> user<span class="gtkdoc opt">-&gt;</span>password<span class="gtkdoc opt">) ==</span> <span class="number">0</span><span class="gtkdoc opt">;</span>
<span class="gtkdoc opt">}</span></pre></td>
      </tr>
    </tbody>
  </table>
</div>

<p>
The <a class="link" href="SoupAuthDomainBasic.html#SoupAuthDomainBasicAuthCallback" title="SoupAuthDomainBasicAuthCallback ()"><span class="type">SoupAuthDomainBasicAuthCallback</span></a>
is given the username and password from the
<code class="literal">Authorization</code> header and must determine, in some
server-specific manner, whether or not to accept them. (In this
example we compare the password against a cleartext password database,
but it would be better to store the password somehow encoded, as in
the UNIX password database. Alternatively, you may need to delegate
the password check to PAM or some other service.)
</p>
<p>
If you are using Digest authentication, note that <a class="link" href="SoupAuthDomainDigest.html#SoupAuthDomainDigestAuthCallback" title="SoupAuthDomainDigestAuthCallback ()"><span class="type">SoupAuthDomainDigestAuthCallback</span></a>
works completely differently (since the server doesn't receive the
cleartext password from the client in that case, so there's no way to
compare it directly). See the documentation for <a class="link" href="SoupAuthDomainDigest.html" title="SoupAuthDomainDigest"><span class="type">SoupAuthDomainDigest</span></a>
for more details.
</p>
<p>
You can have multiple <span class="type">SoupAuthDomain</span>s attached to a
<code class="literal">SoupServer</code>, either in separate parts of the path
hierarchy, or overlapping. (Eg, you might want to accept either Basic
or Digest authentication for a given path.) When more than one auth
domain covers a given path, the request will be accepted if the user
authenticates successfully against <span class="emphasis"><em>any</em></span> of the
domains.
</p>
<p>
If you want to require authentication for some requests under a
certain path, but not all of them (eg, you want to authenticate
<code class="literal">PUT</code> requests, but not <code class="literal">GET</code>
requests), use a <a class="link" href="SoupAuthDomain.html#SoupAuthDomainFilter" title="SoupAuthDomainFilter ()"><span class="type">SoupAuthDomainFilter</span></a>.
</p>
</div>
</div>
<div class="footer">
<hr>Generated by GTK-Doc V1.28.1</div>
</body>
</html>