1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-server.c: Asynchronous HTTP server
5 * Copyright (C) 2001-2003, Ximian, Inc.
17 #include "soup-server.h"
18 #include "soup-address.h"
19 #include "soup-auth-domain.h"
20 #include "soup-date.h"
21 #include "soup-form.h"
22 #include "soup-headers.h"
23 #include "soup-message-private.h"
24 #include "soup-marshal.h"
25 #include "soup-path-map.h"
26 #include "soup-socket.h"
30 * @short_description: HTTP server
31 * @see_also: #SoupAuthDomain
33 * #SoupServer implements a simple HTTP server.
35 * To begin, create a server using soup_server_new(). Add at least one
36 * handler by calling soup_server_add_handler(); the handler will be
37 * called to process any requests underneath the path passed to
38 * soup_server_add_handler(). (If you want all requests to go to the
39 * same handler, just pass "/" (or %NULL) for the path.) Any request
40 * that does not match any handler will automatically be returned to
41 * the client with a 404 (Not Found) status.
43 * If you want to handle the special "*" URI (eg, "OPTIONS *"), you
44 * must explicitly register a handler for "*"; the default handler
45 * will not be used for that case.
47 * To add authentication to some or all paths, create an appropriate
48 * #SoupAuthDomain (qv), and add it to the server via
49 * soup_server_add_auth_domain(). (As with handlers, you must
50 * explicitly add "*" to an auth domain if you want it to be covered.)
52 * Additional processing options are available via #SoupServer's
53 * signals; Connect to #SoupServer::request-started to be notified
54 * every time a new request is being processed. (This gives you a
55 * chance to connect to the #SoupMessage "got-" signals in case you
56 * want to do processing before the body has been fully read.)
58 * Once the server is set up, start it processing connections by
59 * calling soup_server_run_async() or soup_server_run(). #SoupServer
60 * runs via the glib main loop; if you need to have a server that runs
61 * in another thread (or merely isn't bound to the default main loop),
62 * create a #GMainContext for it to use, and set that via the
63 * #SOUP_SERVER_ASYNC_CONTEXT property.
66 G_DEFINE_TYPE (SoupServer, soup_server, G_TYPE_OBJECT)
76 static guint signals[LAST_SIGNAL] = { 0 };
78 struct SoupClientContext {
82 SoupAuthDomain *auth_domain;
91 SoupServerCallback callback;
92 GDestroyNotify destroy;
100 char *ssl_cert_file, *ssl_key_file;
101 GTlsCertificate *ssl_cert;
107 SoupSocket *listen_sock;
111 SoupPathMap *handlers;
112 SoupServerHandler *default_handler;
114 GSList *auth_domains;
116 GMainContext *async_context;
118 #define SOUP_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SERVER, SoupServerPrivate))
120 #define SOUP_SERVER_SERVER_HEADER_BASE "libsoup/" PACKAGE_VERSION
129 PROP_TLS_CERTIFICATE,
137 static GObject *constructor (GType type,
138 guint n_construct_properties,
139 GObjectConstructParam *construct_properties);
140 static void set_property (GObject *object, guint prop_id,
141 const GValue *value, GParamSpec *pspec);
142 static void get_property (GObject *object, guint prop_id,
143 GValue *value, GParamSpec *pspec);
145 static SoupClientContext *soup_client_context_ref (SoupClientContext *client);
146 static void soup_client_context_unref (SoupClientContext *client);
149 free_handler (SoupServerHandler *hand)
152 g_slice_free (SoupServerHandler, hand);
156 soup_server_init (SoupServer *server)
158 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
160 priv->handlers = soup_path_map_new ((GDestroyNotify)free_handler);
164 finalize (GObject *object)
166 SoupServer *server = SOUP_SERVER (object);
167 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
171 g_object_unref (priv->iface);
173 g_free (priv->ssl_cert_file);
174 g_free (priv->ssl_key_file);
176 g_object_unref (priv->ssl_cert);
178 g_free (priv->server_header);
180 if (priv->listen_sock)
181 g_object_unref (priv->listen_sock);
183 while (priv->clients) {
184 SoupClientContext *client = priv->clients->data;
185 SoupSocket *sock = g_object_ref (client->sock);
187 priv->clients = g_slist_remove (priv->clients, client);
189 /* keep a ref on the client context so it doesn't get destroyed
190 * when we finish the message; the SoupSocket::disconnect
191 * handler will refer to client->server later when the socket is
194 soup_client_context_ref (client);
197 soup_message_set_status (client->msg, SOUP_STATUS_IO_ERROR);
198 soup_message_io_finished (client->msg);
201 soup_socket_disconnect (sock);
202 g_object_unref (sock);
204 soup_client_context_unref (client);
207 if (priv->default_handler)
208 free_handler (priv->default_handler);
209 soup_path_map_free (priv->handlers);
211 for (iter = priv->auth_domains; iter; iter = iter->next)
212 g_object_unref (iter->data);
213 g_slist_free (priv->auth_domains);
216 g_main_loop_unref (priv->loop);
217 if (priv->async_context)
218 g_main_context_unref (priv->async_context);
220 G_OBJECT_CLASS (soup_server_parent_class)->finalize (object);
224 soup_server_class_init (SoupServerClass *server_class)
226 GObjectClass *object_class = G_OBJECT_CLASS (server_class);
228 g_type_class_add_private (server_class, sizeof (SoupServerPrivate));
230 /* virtual method override */
231 object_class->constructor = constructor;
232 object_class->finalize = finalize;
233 object_class->set_property = set_property;
234 object_class->get_property = get_property;
239 * SoupServer::request-started:
240 * @server: the server
241 * @message: the new message
242 * @client: the client context
244 * Emitted when the server has started reading a new request.
245 * @message will be completely blank; not even the
246 * Request-Line will have been read yet. About the only thing
247 * you can usefully do with it is connect to its signals.
249 * If the request is read successfully, this will eventually
250 * be followed by a #SoupServer::request_read signal. If a
251 * response is then sent, the request processing will end with
252 * a #SoupServer::request_finished signal. If a network error
253 * occurs, the processing will instead end with
254 * #SoupServer::request_aborted.
256 signals[REQUEST_STARTED] =
257 g_signal_new ("request-started",
258 G_OBJECT_CLASS_TYPE (object_class),
260 G_STRUCT_OFFSET (SoupServerClass, request_started),
262 _soup_marshal_NONE__OBJECT_POINTER,
265 SOUP_TYPE_CLIENT_CONTEXT);
268 * SoupServer::request-read:
269 * @server: the server
270 * @message: the message
271 * @client: the client context
273 * Emitted when the server has successfully read a request.
274 * @message will have all of its request-side information
275 * filled in, and if the message was authenticated, @client
276 * will have information about that. This signal is emitted
277 * before any handlers are called for the message, and if it
278 * sets the message's #status_code, then normal handler
279 * processing will be skipped.
281 signals[REQUEST_READ] =
282 g_signal_new ("request-read",
283 G_OBJECT_CLASS_TYPE (object_class),
285 G_STRUCT_OFFSET (SoupServerClass, request_read),
287 _soup_marshal_NONE__OBJECT_POINTER,
290 SOUP_TYPE_CLIENT_CONTEXT);
293 * SoupServer::request-finished:
294 * @server: the server
295 * @message: the message
296 * @client: the client context
298 * Emitted when the server has finished writing a response to
301 signals[REQUEST_FINISHED] =
302 g_signal_new ("request-finished",
303 G_OBJECT_CLASS_TYPE (object_class),
305 G_STRUCT_OFFSET (SoupServerClass, request_finished),
307 _soup_marshal_NONE__OBJECT_POINTER,
310 SOUP_TYPE_CLIENT_CONTEXT);
313 * SoupServer::request-aborted:
314 * @server: the server
315 * @message: the message
316 * @client: the client context
318 * Emitted when processing has failed for a message; this
319 * could mean either that it could not be read (if
320 * #SoupServer::request_read has not been emitted for it yet),
321 * or that the response could not be written back (if
322 * #SoupServer::request_read has been emitted but
323 * #SoupServer::request_finished has not been).
325 * @message is in an undefined state when this signal is
326 * emitted; the signal exists primarily to allow the server to
327 * free any state that it may have allocated in
328 * #SoupServer::request_started.
330 signals[REQUEST_ABORTED] =
331 g_signal_new ("request-aborted",
332 G_OBJECT_CLASS_TYPE (object_class),
334 G_STRUCT_OFFSET (SoupServerClass, request_aborted),
336 _soup_marshal_NONE__OBJECT_POINTER,
339 SOUP_TYPE_CLIENT_CONTEXT);
345 * Alias for the #SoupServer:port property. (The port the
346 * server listens on.)
348 g_object_class_install_property (
349 object_class, PROP_PORT,
350 g_param_spec_uint (SOUP_SERVER_PORT,
354 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
356 * SOUP_SERVER_INTERFACE:
358 * Alias for the #SoupServer:interface property. (The address
359 * of the network interface the server listens on.)
361 g_object_class_install_property (
362 object_class, PROP_INTERFACE,
363 g_param_spec_object (SOUP_SERVER_INTERFACE,
365 "Address of interface to listen on",
367 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
369 * SOUP_SERVER_SSL_CERT_FILE:
371 * Alias for the #SoupServer:ssl-cert-file property, qv.
374 * SoupServer:ssl-cert-file:
376 * Path to a file containing a PEM-encoded certificate. If
377 * this and #SoupServer:ssl-key-file are both set, then the
378 * server will speak https rather than plain http.
380 * Alternatively, you can use #SoupServer:tls-certificate
381 * to provide an arbitrary #GTlsCertificate.
383 g_object_class_install_property (
384 object_class, PROP_SSL_CERT_FILE,
385 g_param_spec_string (SOUP_SERVER_SSL_CERT_FILE,
386 "SSL certificate file",
387 "File containing server SSL certificate",
389 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
391 * SOUP_SERVER_SSL_KEY_FILE:
393 * Alias for the #SoupServer:ssl-key-file property, qv.
396 * SoupServer:ssl-key-file:
398 * Path to a file containing a PEM-encoded private key. If
399 * this and #SoupServer:ssl-key-file are both set, then the
400 * server will speak https rather than plain http. Note that
401 * you are allowed to set them to the same value, if you have
402 * a single file containing both the certificate and the key.
404 * Alternatively, you can use #SoupServer:tls-certificate
405 * to provide an arbitrary #GTlsCertificate.
407 g_object_class_install_property (
408 object_class, PROP_SSL_KEY_FILE,
409 g_param_spec_string (SOUP_SERVER_SSL_KEY_FILE,
411 "File containing server SSL key",
413 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
415 * SOUP_SERVER_TLS_CERTIFICATE:
417 * Alias for the #SoupServer:tls-certificate property, qv.
420 * SoupServer:tls-certificate:
422 * A #GTlsCertificate that has a #GTlsCertificate:private-key
423 * set. If this is set, then the server will speak https
424 * rather than plain http.
426 * Alternatively, you can use #SoupServer:ssl-cert-file and
427 * #SoupServer:ssl-key-file properties, to have #SoupServer
428 * read in a a certificate from a file.
430 g_object_class_install_property (
431 object_class, PROP_TLS_CERTIFICATE,
432 g_param_spec_object (SOUP_SERVER_TLS_CERTIFICATE,
434 "GTlsCertificate to use for https",
435 G_TYPE_TLS_CERTIFICATE,
436 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
438 * SOUP_SERVER_ASYNC_CONTEXT:
440 * Alias for the #SoupServer:async-context property. (The
441 * server's #GMainContext.)
443 g_object_class_install_property (
444 object_class, PROP_ASYNC_CONTEXT,
445 g_param_spec_pointer (SOUP_SERVER_ASYNC_CONTEXT,
446 "Async GMainContext",
447 "The GMainContext to dispatch async I/O in",
448 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
450 * SOUP_SERVER_RAW_PATHS:
452 * Alias for the #SoupServer:raw-paths property. (If %TRUE,
453 * percent-encoding in the Request-URI path will not be
454 * automatically decoded.)
456 g_object_class_install_property (
457 object_class, PROP_RAW_PATHS,
458 g_param_spec_boolean (SOUP_SERVER_RAW_PATHS,
460 "If %TRUE, percent-encoding in the Request-URI path will not be automatically decoded.",
462 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
465 * SoupServer:server-header:
467 * If non-%NULL, the value to use for the "Server" header on
468 * #SoupMessage<!-- -->s processed by this server.
470 * The Server header is the server equivalent of the
471 * User-Agent header, and provides information about the
472 * server and its components. It contains a list of one or
473 * more product tokens, separated by whitespace, with the most
474 * significant product token coming first. The tokens must be
475 * brief, ASCII, and mostly alphanumeric (although "-", "_",
476 * and "." are also allowed), and may optionally include a "/"
477 * followed by a version string. You may also put comments,
478 * enclosed in parentheses, between or after the tokens.
480 * Some HTTP server implementations intentionally do not use
481 * version numbers in their Server header, so that
482 * installations running older versions of the server don't
483 * end up advertising their vulnerability to specific security
486 * As with #SoupSession:user_agent, if you set a
487 * #SoupServer:server_header property that has trailing whitespace,
488 * #SoupServer will append its own product token (eg,
489 * "<literal>libsoup/2.3.2</literal>") to the end of the
493 * SOUP_SERVER_SERVER_HEADER:
495 * Alias for the #SoupServer:server-header property, qv.
497 g_object_class_install_property (
498 object_class, PROP_SERVER_HEADER,
499 g_param_spec_string (SOUP_SERVER_SERVER_HEADER,
503 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
507 constructor (GType type,
508 guint n_construct_properties,
509 GObjectConstructParam *construct_properties)
512 SoupServerPrivate *priv;
514 server = G_OBJECT_CLASS (soup_server_parent_class)->constructor (
515 type, n_construct_properties, construct_properties);
518 priv = SOUP_SERVER_GET_PRIVATE (server);
522 soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4,
526 if (priv->ssl_cert_file && priv->ssl_key_file) {
527 GError *error = NULL;
530 g_object_unref (priv->ssl_cert);
531 priv->ssl_cert = g_tls_certificate_new_from_files (priv->ssl_cert_file, priv->ssl_key_file, &error);
532 if (!priv->ssl_cert) {
533 g_warning ("Could not read SSL certificate from '%s': %s",
534 priv->ssl_cert_file, error->message);
535 g_error_free (error);
536 g_object_unref (server);
542 soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, priv->iface,
543 SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_cert,
544 SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
546 if (!soup_socket_listen (priv->listen_sock)) {
547 g_object_unref (server);
551 /* Re-resolve the interface address, in particular in case
552 * the passed-in address had SOUP_ADDRESS_ANY_PORT.
554 g_object_unref (priv->iface);
555 priv->iface = soup_socket_get_local_address (priv->listen_sock);
556 g_object_ref (priv->iface);
557 priv->port = soup_address_get_port (priv->iface);
563 set_property (GObject *object, guint prop_id,
564 const GValue *value, GParamSpec *pspec)
566 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (object);
571 priv->port = g_value_get_uint (value);
575 g_object_unref (priv->iface);
576 priv->iface = g_value_get_object (value);
578 g_object_ref (priv->iface);
580 case PROP_SSL_CERT_FILE:
581 priv->ssl_cert_file =
582 g_strdup (g_value_get_string (value));
584 case PROP_SSL_KEY_FILE:
586 g_strdup (g_value_get_string (value));
588 case PROP_TLS_CERTIFICATE:
590 g_object_unref (priv->ssl_cert);
591 priv->ssl_cert = g_value_dup_object (value);
593 case PROP_ASYNC_CONTEXT:
594 priv->async_context = g_value_get_pointer (value);
595 if (priv->async_context)
596 g_main_context_ref (priv->async_context);
599 priv->raw_paths = g_value_get_boolean (value);
601 case PROP_SERVER_HEADER:
602 g_free (priv->server_header);
603 header = g_value_get_string (value);
605 priv->server_header = NULL;
607 priv->server_header =
608 g_strdup (SOUP_SERVER_SERVER_HEADER_BASE);
609 } else if (g_str_has_suffix (header, " ")) {
610 priv->server_header =
611 g_strdup_printf ("%s%s", header,
612 SOUP_SERVER_SERVER_HEADER_BASE);
614 priv->server_header = g_strdup (header);
617 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
623 get_property (GObject *object, guint prop_id,
624 GValue *value, GParamSpec *pspec)
626 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (object);
630 g_value_set_uint (value, priv->port);
633 g_value_set_object (value, priv->iface);
635 case PROP_SSL_CERT_FILE:
636 g_value_set_string (value, priv->ssl_cert_file);
638 case PROP_SSL_KEY_FILE:
639 g_value_set_string (value, priv->ssl_key_file);
641 case PROP_TLS_CERTIFICATE:
642 g_value_set_object (value, priv->ssl_cert);
644 case PROP_ASYNC_CONTEXT:
645 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
648 g_value_set_boolean (value, priv->raw_paths);
650 case PROP_SERVER_HEADER:
651 g_value_set_string (value, priv->server_header);
654 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
661 * @optname1: name of first property to set
662 * @...: value of @optname1, followed by additional property/value pairs
664 * Creates a new #SoupServer.
666 * Return value: a new #SoupServer
669 soup_server_new (const char *optname1, ...)
674 va_start (ap, optname1);
675 server = (SoupServer *)g_object_new_valist (SOUP_TYPE_SERVER,
683 * soup_server_get_port:
684 * @server: a #SoupServer
686 * Gets the TCP port that @server is listening on. This is most useful
687 * when you did not request a specific port (or explicitly requested
688 * %SOUP_ADDRESS_ANY_PORT).
690 * Return value: the port @server is listening on.
693 soup_server_get_port (SoupServer *server)
695 g_return_val_if_fail (SOUP_IS_SERVER (server), 0);
697 return SOUP_SERVER_GET_PRIVATE (server)->port;
701 * soup_server_is_https:
702 * @server: a #SoupServer
704 * Checks whether @server is running plain http or https.
706 * In order for a server to run https, you must set the
707 * %SOUP_SERVER_SSL_CERT_FILE and %SOUP_SERVER_SSL_KEY_FILE properties
708 * to provide it with an SSL certificate to use.
710 * Return value: %TRUE if @server is serving https.
713 soup_server_is_https (SoupServer *server)
715 SoupServerPrivate *priv;
717 g_return_val_if_fail (SOUP_IS_SERVER (server), 0);
718 priv = SOUP_SERVER_GET_PRIVATE (server);
720 return (priv->ssl_cert_file && priv->ssl_key_file);
724 * soup_server_get_listener:
725 * @server: a #SoupServer
727 * Gets @server's listening socket. You should treat this as
728 * read-only; writing to it or modifiying it may cause @server to
731 * Return value: (transfer none): the listening socket.
734 soup_server_get_listener (SoupServer *server)
736 SoupServerPrivate *priv;
738 g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
739 priv = SOUP_SERVER_GET_PRIVATE (server);
741 return priv->listen_sock;
744 static void start_request (SoupServer *, SoupClientContext *);
746 static SoupClientContext *
747 soup_client_context_new (SoupServer *server, SoupSocket *sock)
749 SoupClientContext *client = g_slice_new0 (SoupClientContext);
751 client->server = server;
753 client->ref_count = 1;
759 soup_client_context_cleanup (SoupClientContext *client)
761 if (client->auth_domain) {
762 g_object_unref (client->auth_domain);
763 client->auth_domain = NULL;
765 if (client->auth_user) {
766 g_free (client->auth_user);
767 client->auth_user = NULL;
772 static SoupClientContext *
773 soup_client_context_ref (SoupClientContext *client)
780 soup_client_context_unref (SoupClientContext *client)
782 if (--client->ref_count == 0) {
783 soup_client_context_cleanup (client);
784 g_slice_free (SoupClientContext, client);
789 request_finished (SoupMessage *msg, gpointer user_data)
791 SoupClientContext *client = user_data;
792 SoupServer *server = client->server;
793 SoupSocket *sock = client->sock;
795 soup_message_finished (msg);
796 g_signal_emit (server,
797 msg->status_code == SOUP_STATUS_IO_ERROR ?
798 signals[REQUEST_ABORTED] : signals[REQUEST_FINISHED],
801 soup_client_context_cleanup (client);
802 if (soup_socket_is_connected (sock) && soup_message_is_keepalive (msg)) {
803 /* Start a new request */
804 start_request (server, client);
806 soup_socket_disconnect (sock);
807 soup_client_context_unref (client);
809 g_object_unref (msg);
810 g_object_unref (sock);
813 static SoupServerHandler *
814 soup_server_get_handler (SoupServer *server, const char *path)
816 SoupServerPrivate *priv;
817 SoupServerHandler *hand;
819 g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
820 priv = SOUP_SERVER_GET_PRIVATE (server);
823 hand = soup_path_map_lookup (priv->handlers, path);
826 if (!strcmp (path, "*"))
829 return priv->default_handler;
833 got_headers (SoupMessage *req, SoupClientContext *client)
835 SoupServer *server = client->server;
836 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
840 SoupAuthDomain *domain;
842 gboolean rejected = FALSE;
845 if (!priv->raw_paths) {
848 uri = soup_message_get_uri (req);
849 decoded_path = soup_uri_decode (uri->path);
851 if (strstr (decoded_path, "/../") ||
852 g_str_has_suffix (decoded_path, "/..")) {
853 /* Introducing new ".." segments is not allowed */
854 g_free (decoded_path);
855 soup_message_set_status (req, SOUP_STATUS_BAD_REQUEST);
859 soup_uri_set_path (uri, decoded_path);
860 g_free (decoded_path);
863 /* Add required response headers */
864 date = soup_date_new_from_now (0);
865 date_string = soup_date_to_string (date, SOUP_DATE_HTTP);
866 soup_message_headers_replace (req->response_headers, "Date",
868 g_free (date_string);
869 soup_date_free (date);
871 /* Now handle authentication. (We do this here so that if
872 * the request uses "Expect: 100-continue", we can reject it
873 * immediately rather than waiting for the request body to
876 for (iter = priv->auth_domains; iter; iter = iter->next) {
879 if (soup_auth_domain_covers (domain, req)) {
880 auth_user = soup_auth_domain_accepts (domain, req);
882 client->auth_domain = g_object_ref (domain);
883 client->auth_user = auth_user;
891 /* If no auth domain rejected it, then it's ok. */
895 for (iter = priv->auth_domains; iter; iter = iter->next) {
898 if (soup_auth_domain_covers (domain, req))
899 soup_auth_domain_challenge (domain, req);
904 call_handler (SoupMessage *req, SoupClientContext *client)
906 SoupServer *server = client->server;
907 SoupServerHandler *hand;
910 g_signal_emit (server, signals[REQUEST_READ], 0, req, client);
912 if (req->status_code != 0)
915 uri = soup_message_get_uri (req);
916 hand = soup_server_get_handler (server, uri->path);
918 soup_message_set_status (req, SOUP_STATUS_NOT_FOUND);
922 if (hand->callback) {
923 GHashTable *form_data_set;
926 form_data_set = soup_form_decode (uri->query);
928 form_data_set = NULL;
930 /* Call method handler */
931 (*hand->callback) (server, req,
932 uri->path, form_data_set,
933 client, hand->user_data);
936 g_hash_table_destroy (form_data_set);
941 start_request (SoupServer *server, SoupClientContext *client)
943 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
946 soup_client_context_cleanup (client);
948 /* Listen for another request on this connection */
949 msg = g_object_new (SOUP_TYPE_MESSAGE,
950 SOUP_MESSAGE_SERVER_SIDE, TRUE,
954 if (priv->server_header) {
955 soup_message_headers_append (msg->response_headers, "Server",
956 priv->server_header);
959 g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), client);
960 g_signal_connect (msg, "got_body", G_CALLBACK (call_handler), client);
962 g_signal_emit (server, signals[REQUEST_STARTED], 0,
965 g_object_ref (client->sock);
966 soup_message_read_request (msg, client->sock,
967 request_finished, client);
971 socket_disconnected (SoupSocket *sock, SoupClientContext *client)
973 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (client->server);
975 priv->clients = g_slist_remove (priv->clients, client);
976 g_signal_handlers_disconnect_by_func (sock, socket_disconnected, client);
977 g_object_unref (sock);
981 new_connection (SoupSocket *listner, SoupSocket *sock, gpointer user_data)
983 SoupServer *server = user_data;
984 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
985 SoupClientContext *client;
987 client = soup_client_context_new (server, g_object_ref (sock));
988 priv->clients = g_slist_prepend (priv->clients, client);
989 g_signal_connect (sock, "disconnected",
990 G_CALLBACK (socket_disconnected), client);
991 start_request (server, client);
995 * soup_server_run_async:
996 * @server: a #SoupServer
998 * Starts @server, causing it to listen for and process incoming
1001 * The server actually runs in @server's #GMainContext. It will not
1002 * actually perform any processing unless the appropriate main loop is
1003 * running. In the simple case where you did not set the server's
1004 * %SOUP_SERVER_ASYNC_CONTEXT property, this means the server will run
1005 * whenever the glib main loop is running.
1008 soup_server_run_async (SoupServer *server)
1010 SoupServerPrivate *priv;
1012 g_return_if_fail (SOUP_IS_SERVER (server));
1013 priv = SOUP_SERVER_GET_PRIVATE (server);
1015 if (!priv->listen_sock) {
1017 g_main_loop_unref (priv->loop);
1023 g_signal_connect (priv->listen_sock, "new_connection",
1024 G_CALLBACK (new_connection), server);
1032 * @server: a #SoupServer
1034 * Starts @server, causing it to listen for and process incoming
1035 * connections. Unlike soup_server_run_async(), this creates a
1036 * #GMainLoop and runs it, and it will not return until someone calls
1037 * soup_server_quit() to stop the server.
1040 soup_server_run (SoupServer *server)
1042 SoupServerPrivate *priv;
1044 g_return_if_fail (SOUP_IS_SERVER (server));
1045 priv = SOUP_SERVER_GET_PRIVATE (server);
1048 priv->loop = g_main_loop_new (priv->async_context, TRUE);
1049 soup_server_run_async (server);
1053 g_main_loop_run (priv->loop);
1058 * @server: a #SoupServer
1060 * Stops processing for @server. Call this to clean up after
1061 * soup_server_run_async(), or to terminate a call to soup_server_run().
1063 * @server is still in a working state after this call; you can start
1064 * and stop a server as many times as you want.
1067 soup_server_quit (SoupServer *server)
1069 SoupServerPrivate *priv;
1071 g_return_if_fail (SOUP_IS_SERVER (server));
1072 priv = SOUP_SERVER_GET_PRIVATE (server);
1074 g_signal_handlers_disconnect_by_func (priv->listen_sock,
1075 G_CALLBACK (new_connection),
1078 g_main_loop_quit (priv->loop);
1082 * soup_server_disconnect:
1083 * @server: a #SoupServer
1085 * Stops processing for @server and closes its socket. This implies
1086 * the effects of soup_server_quit(), but additionally closes the
1087 * listening socket. Note that messages currently in progress will
1088 * continue to be handled, if the main loop associated with the
1089 * server is resumed or kept running.
1091 * After calling this function, @server is no longer functional, so it
1092 * has nearly the same effect as destroying @server entirely. The
1093 * function is thus useful mainly for language bindings without
1094 * explicit control over object lifetime.
1097 soup_server_disconnect (SoupServer *server)
1099 SoupServerPrivate *priv;
1101 g_return_if_fail (SOUP_IS_SERVER (server));
1102 priv = SOUP_SERVER_GET_PRIVATE (server);
1104 soup_server_quit (server);
1106 if (priv->listen_sock) {
1107 soup_socket_disconnect (priv->listen_sock);
1108 g_object_unref (priv->listen_sock);
1109 priv->listen_sock = NULL;
1114 * soup_server_get_async_context:
1115 * @server: a #SoupServer
1117 * Gets @server's async_context. This does not add a ref to the
1118 * context, so you will need to ref it yourself if you want it to
1119 * outlive its server.
1121 * Return value: (transfer none): @server's #GMainContext, which may be %NULL
1124 soup_server_get_async_context (SoupServer *server)
1126 SoupServerPrivate *priv;
1128 g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
1129 priv = SOUP_SERVER_GET_PRIVATE (server);
1131 return priv->async_context;
1135 * SoupClientContext:
1137 * A #SoupClientContext provides additional information about the
1138 * client making a particular request. In particular, you can use
1139 * soup_client_context_get_auth_domain() and
1140 * soup_client_context_get_auth_user() to determine if HTTP
1141 * authentication was used successfully.
1143 * soup_client_context_get_address() and/or
1144 * soup_client_context_get_host() can be used to get information for
1145 * logging or debugging purposes. soup_client_context_get_socket() may
1146 * also be of use in some situations (eg, tracking when multiple
1147 * requests are made on the same connection).
1150 soup_client_context_get_type (void)
1152 static volatile gsize type_volatile = 0;
1154 if (g_once_init_enter (&type_volatile)) {
1155 GType type = g_boxed_type_register_static (
1156 g_intern_static_string ("SoupClientContext"),
1157 (GBoxedCopyFunc) soup_client_context_ref,
1158 (GBoxedFreeFunc) soup_client_context_unref);
1159 g_once_init_leave (&type_volatile, type);
1161 return type_volatile;
1165 * soup_client_context_get_socket:
1166 * @client: a #SoupClientContext
1168 * Retrieves the #SoupSocket that @client is associated with.
1170 * If you are using this method to observe when multiple requests are
1171 * made on the same persistent HTTP connection (eg, as the ntlm-test
1172 * test program does), you will need to pay attention to socket
1173 * destruction as well (either by using weak references, or by
1174 * connecting to the #SoupSocket::disconnected signal), so that you do
1175 * not get fooled when the allocator reuses the memory address of a
1176 * previously-destroyed socket to represent a new socket.
1178 * Return value: (transfer none): the #SoupSocket that @client is
1182 soup_client_context_get_socket (SoupClientContext *client)
1184 g_return_val_if_fail (client != NULL, NULL);
1186 return client->sock;
1190 * soup_client_context_get_address:
1191 * @client: a #SoupClientContext
1193 * Retrieves the #SoupAddress associated with the remote end
1196 * Return value: (transfer none): the #SoupAddress associated with the
1197 * remote end of a connection.
1200 soup_client_context_get_address (SoupClientContext *client)
1202 g_return_val_if_fail (client != NULL, NULL);
1204 return soup_socket_get_remote_address (client->sock);
1208 * soup_client_context_get_host:
1209 * @client: a #SoupClientContext
1211 * Retrieves the IP address associated with the remote end of a
1212 * connection. (If you want the actual hostname, you'll have to call
1213 * soup_client_context_get_address() and then call the appropriate
1214 * #SoupAddress method to resolve it.)
1216 * Return value: the IP address associated with the remote end of a
1220 soup_client_context_get_host (SoupClientContext *client)
1222 SoupAddress *address;
1224 address = soup_client_context_get_address (client);
1225 return soup_address_get_physical (address);
1229 * soup_client_context_get_auth_domain:
1230 * @client: a #SoupClientContext
1232 * Checks whether the request associated with @client has been
1233 * authenticated, and if so returns the #SoupAuthDomain that
1236 * Return value: (transfer none) (allow-none): a #SoupAuthDomain, or
1237 * %NULL if the request was not authenticated.
1240 soup_client_context_get_auth_domain (SoupClientContext *client)
1242 g_return_val_if_fail (client != NULL, NULL);
1244 return client->auth_domain;
1248 * soup_client_context_get_auth_user:
1249 * @client: a #SoupClientContext
1251 * Checks whether the request associated with @client has been
1252 * authenticated, and if so returns the username that the client
1255 * Return value: the authenticated-as user, or %NULL if the request
1256 * was not authenticated.
1259 soup_client_context_get_auth_user (SoupClientContext *client)
1261 g_return_val_if_fail (client != NULL, NULL);
1263 return client->auth_user;
1267 * SoupServerCallback:
1268 * @server: the #SoupServer
1269 * @msg: the message being processed
1270 * @path: the path component of @msg's Request-URI
1271 * @query: (element-type utf8 utf8) (allow-none): the parsed query
1272 * component of @msg's Request-URI
1273 * @client: additional contextual information about the client
1274 * @user_data: the data passed to @soup_server_add_handler
1276 * A callback used to handle requests to a #SoupServer. The callback
1277 * will be invoked after receiving the request body; @msg's
1278 * #SoupMessage:method, #SoupMessage:request_headers, and
1279 * #SoupMessage:request_body fields will be filled in.
1281 * @path and @query contain the likewise-named components of the
1282 * Request-URI, subject to certain assumptions. By default,
1283 * #SoupServer decodes all percent-encoding in the URI path, such that
1284 * "/foo%<!-- -->2Fbar" is treated the same as "/foo/bar". If your
1285 * server is serving resources in some non-POSIX-filesystem namespace,
1286 * you may want to distinguish those as two distinct paths. In that
1287 * case, you can set the %SOUP_SERVER_RAW_PATHS property when creating
1288 * the #SoupServer, and it will leave those characters undecoded. (You
1289 * may want to call soup_uri_normalize() to decode any percent-encoded
1290 * characters that you aren't handling specially.)
1292 * @query contains the query component of the Request-URI parsed
1293 * according to the rules for HTML form handling. Although this is the
1294 * only commonly-used query string format in HTTP, there is nothing
1295 * that actually requires that HTTP URIs use that format; if your
1296 * server needs to use some other format, you can just ignore @query,
1297 * and call soup_message_get_uri() and parse the URI's query field
1300 * After determining what to do with the request, the callback must at
1301 * a minimum call soup_message_set_status() (or
1302 * soup_message_set_status_full()) on @msg to set the response status
1303 * code. Additionally, it may set response headers and/or fill in the
1306 * If the callback cannot fully fill in the response before returning
1307 * (eg, if it needs to wait for information from a database, or
1308 * another network server), it should call soup_server_pause_message()
1309 * to tell #SoupServer to not send the response right away. When the
1310 * response is ready, call soup_server_unpause_message() to cause it
1313 * To send the response body a bit at a time using "chunked" encoding,
1314 * first call soup_message_headers_set_encoding() to set
1315 * %SOUP_ENCODING_CHUNKED on the #SoupMessage:response_headers. Then call
1316 * soup_message_body_append() (or soup_message_body_append_buffer())
1317 * to append each chunk as it becomes ready, and
1318 * soup_server_unpause_message() to make sure it's running. (The
1319 * server will automatically pause the message if it is using chunked
1320 * encoding but no more chunks are available.) When you are done, call
1321 * soup_message_body_complete() to indicate that no more chunks are
1326 * soup_server_add_handler:
1327 * @server: a #SoupServer
1328 * @path: (allow-none): the toplevel path for the handler
1329 * @callback: callback to invoke for requests under @path
1330 * @user_data: data for @callback
1331 * @destroy: destroy notifier to free @user_data
1333 * Adds a handler to @server for requests under @path. See the
1334 * documentation for #SoupServerCallback for information about
1335 * how callbacks should behave.
1337 * If @path is %NULL or "/", then this will be the default handler for
1338 * all requests that don't have a more specific handler. Note though
1339 * that if you want to handle requests to the special "*" URI, you
1340 * must explicitly register a handler for "*"; the default handler
1341 * will not be used for that case.
1344 soup_server_add_handler (SoupServer *server,
1346 SoupServerCallback callback,
1348 GDestroyNotify destroy)
1350 SoupServerPrivate *priv;
1351 SoupServerHandler *hand;
1353 g_return_if_fail (SOUP_IS_SERVER (server));
1354 g_return_if_fail (callback != NULL);
1355 priv = SOUP_SERVER_GET_PRIVATE (server);
1357 /* "" was never documented as meaning the same this as "/",
1358 * but it effectively was. We have to special case it now or
1359 * otherwise it would match "*" too.
1361 if (path && (!*path || !strcmp (path, "/")))
1364 hand = g_slice_new0 (SoupServerHandler);
1365 hand->path = g_strdup (path);
1366 hand->callback = callback;
1367 hand->destroy = destroy;
1368 hand->user_data = user_data;
1370 soup_server_remove_handler (server, path);
1372 soup_path_map_add (priv->handlers, path, hand);
1374 priv->default_handler = hand;
1378 unregister_handler (SoupServerHandler *handler)
1380 if (handler->destroy)
1381 handler->destroy (handler->user_data);
1385 * soup_server_remove_handler:
1386 * @server: a #SoupServer
1387 * @path: the toplevel path for the handler
1389 * Removes the handler registered at @path.
1392 soup_server_remove_handler (SoupServer *server, const char *path)
1394 SoupServerPrivate *priv;
1395 SoupServerHandler *hand;
1397 g_return_if_fail (SOUP_IS_SERVER (server));
1398 priv = SOUP_SERVER_GET_PRIVATE (server);
1400 if (!path || !*path || !strcmp (path, "/")) {
1401 if (priv->default_handler) {
1402 unregister_handler (priv->default_handler);
1403 free_handler (priv->default_handler);
1404 priv->default_handler = NULL;
1409 hand = soup_path_map_lookup (priv->handlers, path);
1410 if (hand && !strcmp (path, hand->path)) {
1411 unregister_handler (hand);
1412 soup_path_map_remove (priv->handlers, path);
1417 * soup_server_add_auth_domain:
1418 * @server: a #SoupServer
1419 * @auth_domain: a #SoupAuthDomain
1421 * Adds an authentication domain to @server. Each auth domain will
1422 * have the chance to require authentication for each request that
1423 * comes in; normally auth domains will require authentication for
1424 * requests on certain paths that they have been set up to watch, or
1425 * that meet other criteria set by the caller. If an auth domain
1426 * determines that a request requires authentication (and the request
1427 * doesn't contain authentication), @server will automatically reject
1428 * the request with an appropriate status (401 Unauthorized or 407
1429 * Proxy Authentication Required). If the request used the
1430 * "100-continue" Expectation, @server will reject it before the
1431 * request body is sent.
1434 soup_server_add_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain)
1436 SoupServerPrivate *priv;
1438 g_return_if_fail (SOUP_IS_SERVER (server));
1439 priv = SOUP_SERVER_GET_PRIVATE (server);
1441 priv->auth_domains = g_slist_append (priv->auth_domains, auth_domain);
1442 g_object_ref (auth_domain);
1446 * soup_server_remove_auth_domain:
1447 * @server: a #SoupServer
1448 * @auth_domain: a #SoupAuthDomain
1450 * Removes @auth_domain from @server.
1453 soup_server_remove_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain)
1455 SoupServerPrivate *priv;
1457 g_return_if_fail (SOUP_IS_SERVER (server));
1458 priv = SOUP_SERVER_GET_PRIVATE (server);
1460 priv->auth_domains = g_slist_remove (priv->auth_domains, auth_domain);
1461 g_object_unref (auth_domain);
1465 * soup_server_pause_message:
1466 * @server: a #SoupServer
1467 * @msg: a #SoupMessage associated with @server.
1469 * Pauses I/O on @msg. This can be used when you need to return from
1470 * the server handler without having the full response ready yet. Use
1471 * soup_server_unpause_message() to resume I/O.
1474 soup_server_pause_message (SoupServer *server,
1477 g_return_if_fail (SOUP_IS_SERVER (server));
1478 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1480 soup_message_io_pause (msg);
1484 * soup_server_unpause_message:
1485 * @server: a #SoupServer
1486 * @msg: a #SoupMessage associated with @server.
1488 * Resumes I/O on @msg. Use this to resume after calling
1489 * soup_server_pause_message(), or after adding a new chunk to a
1492 * I/O won't actually resume until you return to the main loop.
1495 soup_server_unpause_message (SoupServer *server,
1498 g_return_if_fail (SOUP_IS_SERVER (server));
1499 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1501 soup_message_io_unpause (msg);