/usr/share/gtk-doc/html/libsoup-2.4/libsoup-server-howto.html is in libsoup2.4-doc 2.44.2-1ubuntu2.3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | <!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 Reference Manual: Soup Server Basics</title>
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="index.html" title="libsoup Reference Manual">
<link rel="up" href="ch01.html" title="Tutorial">
<link rel="prev" href="libsoup-client-howto.html" title="Soup Client Basics">
<link rel="next" href="libsoup-session-porting.html" title="Porting to the new SoupSession">
<meta name="generator" content="GTK-Doc V1.20 (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="10"><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-client-howto.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
<td><a accesskey="n" href="libsoup-session-porting.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">Soup Server Basics</span></h2>
<p>Soup 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.4.3"></a><h3>Creating a SoupSession</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
various 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-PORT:CAPS" title="SOUP_SERVER_PORT"><code class="literal">SOUP_SERVER_PORT</code></a></span></p></td>
<td><p>
The TCP port to listen on. If <code class="literal">0</code> (or
left unspecified), some unused port will be selected for
you. (You can find out what port by calling <a class="link" href="SoupServer.html#soup-server-get-port" title="soup_server_get_port ()"><code class="function">soup_server_get_port</code></a>.
</p></td>
</tr>
<tr>
<td><p><span class="term"><a class="link" href="SoupServer.html#SOUP-SERVER-INTERFACE:CAPS" title="SOUP_SERVER_INTERFACE"><code class="literal">SOUP_SERVER_INTERFACE</code></a></span></p></td>
<td><p>
A <a class="link" href="SoupAddress.html" title="SoupAddress"><span class="type">SoupAddress</span></a>,
specifying the IP address of the network interface to run
the server on. If <code class="literal">NULL</code> (or left
unspecified), the server will listen on all interfaces.
</p></td>
</tr>
<tr>
<td><p><span class="term"><a class="link" href="SoupServer.html#SOUP-SERVER-SSL-CERT-FILE:CAPS" title="SOUP_SERVER_SSL_CERT_FILE"><code class="literal">SOUP_SERVER_SSL_CERT_FILE</code></a></span></p></td>
<td><p>
Points to a file containing an SSL certificate to use. If
this is set, then the server will speak HTTPS; otherwise
it will speak HTTP.
</p></td>
</tr>
<tr>
<td><p><span class="term"><a class="link" href="SoupServer.html#SOUP-SERVER-SSL-KEY-FILE:CAPS" title="SOUP_SERVER_SSL_KEY_FILE"><code class="literal">SOUP_SERVER_SSL_KEY_FILE</code></a></span></p></td>
<td><p>
Points to a file containing the private key for the
<code class="literal">SOUP_SERVER_SSL_CERT_FILE</code>. (It may
point to the same file.)
</p></td>
</tr>
<tr>
<td><p><span class="term"><a class="link" href="SoupServer.html#SOUP-SERVER-ASYNC-CONTEXT:CAPS" title="SOUP_SERVER_ASYNC_CONTEXT"><code class="literal">SOUP_SERVER_ASYNC_CONTEXT</code></a></span></p></td>
<td><p>
A <a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a> which
the server will use for asynchronous operations. This can
be set if you want to use a SoupServer in a thread
other than the main thread.
</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>
</tbody>
</table></div>
</div>
<hr>
<div class="refsect2">
<a name="id-1.2.4.4"></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"><pre class="programlisting">
soup_server_add_handler (server, "/foo", server_callback,
data, destroy_notify);
</pre></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&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.4.5"></a><h3>Responding to Requests</h3>
<p>
A handler callback looks something like this:
</p>
<div class="informalexample"><pre class="programlisting">
static void
server_callback (SoupServer *server,
SoupMessage *msg,
const char *path,
GHashTable *query,
SoupClientContext *client,
gpointer user_data)
{
...
}
</pre></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.4.5.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"><pre class="programlisting">
static void
server_callback (SoupServer *server,
SoupMessage *msg,
const char *path,
GHashTable *query,
SoupClientContext *client,
gpointer user_data)
{
MyServerData *server_data = user_data;
const char *mime_type;
GByteArray *body;
if (msg->method != SOUP_METHOD_GET) {
soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
return;
}
/* This is somewhat silly. Presumably your server will do
* something more interesting.
*/
body = g_hash_table_lookup (server_data->bodies, path);
mime_type = g_hash_table_lookup (server_data->mime_types, path);
if (!body || !mime_type) {
soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
return;
}
soup_message_set_status (msg, SOUP_STATUS_OK);
soup_message_set_response (msg, mime_type, SOUP_MEMORY_COPY,
body->data, body->len);
}
</pre></div>
</div>
<div class="refsect3">
<a name="id-1.2.4.5.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->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->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">tests/</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.4.6"></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"><pre class="programlisting">
SoupAuthDomain *domain;
domain = soup_auth_domain_basic_new (
SOUP_AUTH_DOMAIN_REALM, "My Realm",
SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback,
SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA, auth_data,
SOUP_AUTH_DOMAIN_ADD_PATH, "/foo",
SOUP_AUTH_DOMAIN_ADD_PATH, "/bar/private",
NULL);
soup_server_add_auth_domain (server, domain);
g_object_unref (domain);
</pre></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"><pre class="programlisting">
static gboolean
auth_callback (SoupAuthDomain *domain, SoupMessage *msg,
const char *username, const char *password,
gpointer user_data)
{
MyServerData *server_data = user_data;
MyUserData *user;
user = my_server_data_lookup_user (server_data, username);
if (!user)
return FALSE;
/* FIXME: Don't do this. Keeping a cleartext password database
* is bad.
*/
return strcmp (password, user->password) == 0;
}
</pre></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>s, but not <code class="literal">GET</code>s), 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.20</div>
</body>
</html>
|