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"
31 * @short_description: HTTP server
32 * @see_also: #SoupAuthDomain
34 * #SoupServer implements a simple HTTP server.
36 * To begin, create a server using soup_server_new(). Add at least one
37 * handler by calling soup_server_add_handler(); the handler will be
38 * called to process any requests underneath the path passed to
39 * soup_server_add_handler(). (If you want all requests to go to the
40 * same handler, just pass "/" (or %NULL) for the path.) Any request
41 * that does not match any handler will automatically be returned to
42 * the client with a 404 (Not Found) status.
44 * If you want to handle the special "*" URI (eg, "OPTIONS *"), you
45 * must explicitly register a handler for "*"; the default handler
46 * will not be used for that case.
48 * To add authentication to some or all paths, create an appropriate
49 * #SoupAuthDomain (qv), and add it to the server via
50 * soup_server_add_auth_domain(). (As with handlers, you must
51 * explicitly add "*" to an auth domain if you want it to be covered.)
53 * Additional processing options are available via #SoupServer's
54 * signals; Connect to #SoupServer::request-started to be notified
55 * every time a new request is being processed. (This gives you a
56 * chance to connect to the #SoupMessage "got-" signals in case you
57 * want to do processing before the body has been fully read.)
59 * Once the server is set up, start it processing connections by
60 * calling soup_server_run_async() or soup_server_run(). #SoupServer
61 * runs via the glib main loop; if you need to have a server that runs
62 * in another thread (or merely isn't bound to the default main loop),
63 * create a #GMainContext for it to use, and set that via the
64 * #SOUP_SERVER_ASYNC_CONTEXT property.
67 G_DEFINE_TYPE (SoupServer, soup_server, G_TYPE_OBJECT)
77 static guint signals[LAST_SIGNAL] = { 0 };
79 struct SoupClientContext {
83 SoupAuthDomain *auth_domain;
92 SoupServerCallback callback;
93 GDestroyNotify destroy;
101 char *ssl_cert_file, *ssl_key_file;
102 SoupSSLCredentials *ssl_creds;
108 SoupSocket *listen_sock;
112 SoupPathMap *handlers;
113 SoupServerHandler *default_handler;
115 GSList *auth_domains;
117 GMainContext *async_context;
119 #define SOUP_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SERVER, SoupServerPrivate))
121 #define SOUP_SERVER_SERVER_HEADER_BASE "libsoup/" PACKAGE_VERSION
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);
146 free_handler (SoupServerHandler *hand)
149 g_slice_free (SoupServerHandler, hand);
153 soup_server_init (SoupServer *server)
155 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
157 priv->handlers = soup_path_map_new ((GDestroyNotify)free_handler);
161 finalize (GObject *object)
163 SoupServer *server = SOUP_SERVER (object);
164 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
168 g_object_unref (priv->iface);
170 g_free (priv->ssl_cert_file);
171 g_free (priv->ssl_key_file);
173 soup_ssl_free_server_credentials (priv->ssl_creds);
175 g_free (priv->server_header);
177 if (priv->listen_sock)
178 g_object_unref (priv->listen_sock);
180 while (priv->clients) {
181 SoupClientContext *client = priv->clients->data;
182 SoupSocket *sock = g_object_ref (client->sock);
184 priv->clients = g_slist_remove (priv->clients, client);
187 soup_message_set_status (client->msg, SOUP_STATUS_IO_ERROR);
188 soup_message_io_finished (client->msg);
191 soup_socket_disconnect (sock);
192 g_object_unref (sock);
195 if (priv->default_handler)
196 free_handler (priv->default_handler);
197 soup_path_map_free (priv->handlers);
199 for (iter = priv->auth_domains; iter; iter = iter->next)
200 g_object_unref (iter->data);
201 g_slist_free (priv->auth_domains);
204 g_main_loop_unref (priv->loop);
205 if (priv->async_context)
206 g_main_context_unref (priv->async_context);
208 G_OBJECT_CLASS (soup_server_parent_class)->finalize (object);
212 soup_server_class_init (SoupServerClass *server_class)
214 GObjectClass *object_class = G_OBJECT_CLASS (server_class);
216 g_type_class_add_private (server_class, sizeof (SoupServerPrivate));
218 /* virtual method override */
219 object_class->constructor = constructor;
220 object_class->finalize = finalize;
221 object_class->set_property = set_property;
222 object_class->get_property = get_property;
227 * SoupServer::request-started
228 * @server: the server
229 * @message: the new message
230 * @client: the client context
232 * Emitted when the server has started reading a new request.
233 * @message will be completely blank; not even the
234 * Request-Line will have been read yet. About the only thing
235 * you can usefully do with it is connect to its signals.
237 * If the request is read successfully, this will eventually
238 * be followed by a #SoupServer::request_read signal. If a
239 * response is then sent, the request processing will end with
240 * a #SoupServer::request_finished signal. If a network error
241 * occurs, the processing will instead end with
242 * #SoupServer::request_aborted.
244 signals[REQUEST_STARTED] =
245 g_signal_new ("request-started",
246 G_OBJECT_CLASS_TYPE (object_class),
248 G_STRUCT_OFFSET (SoupServerClass, request_started),
250 soup_marshal_NONE__OBJECT_POINTER,
253 SOUP_TYPE_CLIENT_CONTEXT);
256 * SoupServer::request-read
257 * @server: the server
258 * @message: the message
259 * @client: the client context
261 * Emitted when the server has successfully read a request.
262 * @message will have all of its request-side information
263 * filled in, and if the message was authenticated, @client
264 * will have information about that. This signal is emitted
265 * before any handlers are called for the message, and if it
266 * sets the message's #status_code, then normal handler
267 * processing will be skipped.
269 signals[REQUEST_READ] =
270 g_signal_new ("request-read",
271 G_OBJECT_CLASS_TYPE (object_class),
273 G_STRUCT_OFFSET (SoupServerClass, request_read),
275 soup_marshal_NONE__OBJECT_POINTER,
278 SOUP_TYPE_CLIENT_CONTEXT);
281 * SoupServer::request-finished
282 * @server: the server
283 * @message: the message
284 * @client: the client context
286 * Emitted when the server has finished writing a response to
289 signals[REQUEST_FINISHED] =
290 g_signal_new ("request-finished",
291 G_OBJECT_CLASS_TYPE (object_class),
293 G_STRUCT_OFFSET (SoupServerClass, request_finished),
295 soup_marshal_NONE__OBJECT_POINTER,
298 SOUP_TYPE_CLIENT_CONTEXT);
301 * SoupServer::request-aborted
302 * @server: the server
303 * @message: the message
304 * @client: the client context
306 * Emitted when processing has failed for a message; this
307 * could mean either that it could not be read (if
308 * #SoupServer::request_read has not been emitted for it yet),
309 * or that the response could not be written back (if
310 * #SoupServer::request_read has been emitted but
311 * #SoupServer::request_finished has not been).
313 * @message is in an undefined state when this signal is
314 * emitted; the signal exists primarily to allow the server to
315 * free any state that it may have allocated in
316 * #SoupServer::request_started.
318 signals[REQUEST_ABORTED] =
319 g_signal_new ("request-aborted",
320 G_OBJECT_CLASS_TYPE (object_class),
322 G_STRUCT_OFFSET (SoupServerClass, request_aborted),
324 soup_marshal_NONE__OBJECT_POINTER,
327 SOUP_TYPE_CLIENT_CONTEXT);
333 * Alias for the #SoupServer:port property. (The port the
334 * server listens on.)
336 g_object_class_install_property (
337 object_class, PROP_PORT,
338 g_param_spec_uint (SOUP_SERVER_PORT,
342 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
344 * SOUP_SERVER_INTERFACE:
346 * Alias for the #SoupServer:interface property. (The address
347 * of the network interface the server listens on.)
349 g_object_class_install_property (
350 object_class, PROP_INTERFACE,
351 g_param_spec_object (SOUP_SERVER_INTERFACE,
353 "Address of interface to listen on",
355 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
357 * SOUP_SERVER_SSL_CERT_FILE:
359 * Alias for the #SoupServer:ssl-cert-file property. (The file
360 * containing the SSL certificate for the server.)
362 g_object_class_install_property (
363 object_class, PROP_SSL_CERT_FILE,
364 g_param_spec_string (SOUP_SERVER_SSL_CERT_FILE,
365 "SSL certificate file",
366 "File containing server SSL certificate",
368 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
370 * SOUP_SERVER_SSL_KEY_FILE:
372 * Alias for the #SoupServer:ssl-key-file property. (The file
373 * containing the SSL certificate key for the server.)
375 g_object_class_install_property (
376 object_class, PROP_SSL_KEY_FILE,
377 g_param_spec_string (SOUP_SERVER_SSL_KEY_FILE,
379 "File containing server SSL key",
381 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
383 * SOUP_SERVER_ASYNC_CONTEXT:
385 * Alias for the #SoupServer:async-context property. (The
386 * server's #GMainContext.)
388 g_object_class_install_property (
389 object_class, PROP_ASYNC_CONTEXT,
390 g_param_spec_pointer (SOUP_SERVER_ASYNC_CONTEXT,
391 "Async GMainContext",
392 "The GMainContext to dispatch async I/O in",
393 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
395 * SOUP_SERVER_RAW_PATHS:
397 * Alias for the #SoupServer:raw-paths property. (If %TRUE,
398 * percent-encoding in the Request-URI path will not be
399 * automatically decoded.)
401 g_object_class_install_property (
402 object_class, PROP_RAW_PATHS,
403 g_param_spec_boolean (SOUP_SERVER_RAW_PATHS,
405 "If %TRUE, percent-encoding in the Request-URI path will not be automatically decoded.",
407 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
410 * SoupServer:server-header:
412 * If non-%NULL, the value to use for the "Server" header on
413 * #SoupMessage<!-- -->s processed by this server.
415 * The Server header is the server equivalent of the
416 * User-Agent header, and provides information about the
417 * server and its components. It contains a list of one or
418 * more product tokens, separated by whitespace, with the most
419 * significant product token coming first. The tokens must be
420 * brief, ASCII, and mostly alphanumeric (although "-", "_",
421 * and "." are also allowed), and may optionally include a "/"
422 * followed by a version string. You may also put comments,
423 * enclosed in parentheses, between or after the tokens.
425 * Some HTTP server implementations intentionally do not use
426 * version numbers in their Server header, so that
427 * installations running older versions of the server don't
428 * end up advertising their vulnerability to specific security
431 * As with #SoupSession:user_agent, if you set a
432 * %server_header property that has trailing whitespace,
433 * #SoupServer will append its own product token (eg,
434 * "<literal>libsoup/2.3.2</literal>") to the end of the
438 * SOUP_SERVER_SERVER_HEADER:
440 * Alias for the #SoupServer:server-header property, qv.
442 g_object_class_install_property (
443 object_class, PROP_SERVER_HEADER,
444 g_param_spec_string (SOUP_SERVER_SERVER_HEADER,
448 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
452 constructor (GType type,
453 guint n_construct_properties,
454 GObjectConstructParam *construct_properties)
457 SoupServerPrivate *priv;
459 server = G_OBJECT_CLASS (soup_server_parent_class)->constructor (
460 type, n_construct_properties, construct_properties);
463 priv = SOUP_SERVER_GET_PRIVATE (server);
467 soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4,
471 if (priv->ssl_cert_file && priv->ssl_key_file) {
472 priv->ssl_creds = soup_ssl_get_server_credentials (
475 if (!priv->ssl_creds) {
476 g_object_unref (server);
482 soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, priv->iface,
483 SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds,
484 SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
486 if (!soup_socket_listen (priv->listen_sock)) {
487 g_object_unref (server);
491 /* Re-resolve the interface address, in particular in case
492 * the passed-in address had SOUP_ADDRESS_ANY_PORT.
494 g_object_unref (priv->iface);
495 priv->iface = soup_socket_get_local_address (priv->listen_sock);
496 g_object_ref (priv->iface);
497 priv->port = soup_address_get_port (priv->iface);
503 set_property (GObject *object, guint prop_id,
504 const GValue *value, GParamSpec *pspec)
506 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (object);
511 priv->port = g_value_get_uint (value);
515 g_object_unref (priv->iface);
516 priv->iface = g_value_get_object (value);
518 g_object_ref (priv->iface);
520 case PROP_SSL_CERT_FILE:
521 priv->ssl_cert_file =
522 g_strdup (g_value_get_string (value));
524 case PROP_SSL_KEY_FILE:
526 g_strdup (g_value_get_string (value));
528 case PROP_ASYNC_CONTEXT:
529 priv->async_context = g_value_get_pointer (value);
530 if (priv->async_context)
531 g_main_context_ref (priv->async_context);
534 priv->raw_paths = g_value_get_boolean (value);
536 case PROP_SERVER_HEADER:
537 g_free (priv->server_header);
538 header = g_value_get_string (value);
540 priv->server_header = NULL;
542 priv->server_header =
543 g_strdup (SOUP_SERVER_SERVER_HEADER_BASE);
544 } else if (g_str_has_suffix (header, " ")) {
545 priv->server_header =
546 g_strdup_printf ("%s%s", header,
547 SOUP_SERVER_SERVER_HEADER_BASE);
549 priv->server_header = g_strdup (header);
552 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
558 get_property (GObject *object, guint prop_id,
559 GValue *value, GParamSpec *pspec)
561 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (object);
565 g_value_set_uint (value, priv->port);
568 g_value_set_object (value, priv->iface);
570 case PROP_SSL_CERT_FILE:
571 g_value_set_string (value, priv->ssl_cert_file);
573 case PROP_SSL_KEY_FILE:
574 g_value_set_string (value, priv->ssl_key_file);
576 case PROP_ASYNC_CONTEXT:
577 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
580 g_value_set_boolean (value, priv->raw_paths);
582 case PROP_SERVER_HEADER:
583 g_value_set_string (value, priv->server_header);
586 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
593 * @optname1: name of first property to set
594 * @...: value of @optname1, followed by additional property/value pairs
596 * Creates a new #SoupServer.
598 * Return value: a new #SoupServer
601 soup_server_new (const char *optname1, ...)
606 va_start (ap, optname1);
607 server = (SoupServer *)g_object_new_valist (SOUP_TYPE_SERVER,
615 * soup_server_get_port:
616 * @server: a #SoupServer
618 * Gets the TCP port that @server is listening on. This is most useful
619 * when you did not request a specific port (or explicitly requested
620 * %SOUP_ADDRESS_ANY_PORT).
622 * Return value: the port @server is listening on.
625 soup_server_get_port (SoupServer *server)
627 g_return_val_if_fail (SOUP_IS_SERVER (server), 0);
629 return SOUP_SERVER_GET_PRIVATE (server)->port;
633 * soup_server_is_https:
634 * @server: a #SoupServer
636 * Checks whether @server is running plain http or https.
638 * In order for a server to run https, you must set the
639 * %SOUP_SERVER_SSL_CERT_FILE and %SOUP_SERVER_SSL_KEY_FILE properties
640 * to provide it with an SSL certificate to use.
642 * Return value: %TRUE if @server is serving https.
645 soup_server_is_https (SoupServer *server)
647 SoupServerPrivate *priv;
649 g_return_val_if_fail (SOUP_IS_SERVER (server), 0);
650 priv = SOUP_SERVER_GET_PRIVATE (server);
652 return (priv->ssl_cert_file && priv->ssl_key_file);
656 * soup_server_get_listener:
657 * @server: a #SoupServer
659 * Gets @server's listening socket. You should treat this as
660 * read-only; writing to it or modifiying it may cause @server to
663 * Return value: (transfer none): the listening socket.
666 soup_server_get_listener (SoupServer *server)
668 SoupServerPrivate *priv;
670 g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
671 priv = SOUP_SERVER_GET_PRIVATE (server);
673 return priv->listen_sock;
676 static void start_request (SoupServer *, SoupClientContext *);
678 static SoupClientContext *
679 soup_client_context_new (SoupServer *server, SoupSocket *sock)
681 SoupClientContext *client = g_slice_new0 (SoupClientContext);
683 client->server = server;
685 client->ref_count = 1;
691 soup_client_context_cleanup (SoupClientContext *client)
693 if (client->auth_domain) {
694 g_object_unref (client->auth_domain);
695 client->auth_domain = NULL;
697 if (client->auth_user) {
698 g_free (client->auth_user);
699 client->auth_user = NULL;
704 static SoupClientContext *
705 soup_client_context_ref (SoupClientContext *client)
712 soup_client_context_unref (SoupClientContext *client)
714 if (--client->ref_count == 0) {
715 soup_client_context_cleanup (client);
716 g_slice_free (SoupClientContext, client);
721 request_finished (SoupMessage *msg, gpointer user_data)
723 SoupClientContext *client = user_data;
724 SoupServer *server = client->server;
725 SoupSocket *sock = client->sock;
727 soup_message_finished (msg);
728 g_signal_emit (server,
729 msg->status_code == SOUP_STATUS_IO_ERROR ?
730 signals[REQUEST_ABORTED] : signals[REQUEST_FINISHED],
733 soup_client_context_cleanup (client);
734 if (soup_socket_is_connected (sock) && soup_message_is_keepalive (msg)) {
735 /* Start a new request */
736 start_request (server, client);
738 soup_socket_disconnect (sock);
739 soup_client_context_unref (client);
741 g_object_unref (msg);
742 g_object_unref (sock);
745 static SoupServerHandler *
746 soup_server_get_handler (SoupServer *server, const char *path)
748 SoupServerPrivate *priv;
749 SoupServerHandler *hand;
751 g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
752 priv = SOUP_SERVER_GET_PRIVATE (server);
755 hand = soup_path_map_lookup (priv->handlers, path);
758 if (!strcmp (path, "*"))
761 return priv->default_handler;
765 got_headers (SoupMessage *req, SoupClientContext *client)
767 SoupServer *server = client->server;
768 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
772 SoupAuthDomain *domain;
774 gboolean rejected = FALSE;
777 if (!priv->raw_paths) {
780 uri = soup_message_get_uri (req);
781 decoded_path = soup_uri_decode (uri->path);
783 if (strstr (decoded_path, "/../") ||
784 g_str_has_suffix (decoded_path, "/..")) {
785 /* Introducing new ".." segments is not allowed */
786 g_free (decoded_path);
787 soup_message_set_status (req, SOUP_STATUS_BAD_REQUEST);
791 soup_uri_set_path (uri, decoded_path);
792 g_free (decoded_path);
795 /* Add required response headers */
796 date = soup_date_new_from_now (0);
797 date_string = soup_date_to_string (date, SOUP_DATE_HTTP);
798 soup_message_headers_replace (req->response_headers, "Date",
800 g_free (date_string);
801 soup_date_free (date);
803 /* Now handle authentication. (We do this here so that if
804 * the request uses "Expect: 100-continue", we can reject it
805 * immediately rather than waiting for the request body to
808 for (iter = priv->auth_domains; iter; iter = iter->next) {
811 if (soup_auth_domain_covers (domain, req)) {
812 auth_user = soup_auth_domain_accepts (domain, req);
814 client->auth_domain = g_object_ref (domain);
815 client->auth_user = auth_user;
823 /* If no auth domain rejected it, then it's ok. */
827 for (iter = priv->auth_domains; iter; iter = iter->next) {
830 if (soup_auth_domain_covers (domain, req))
831 soup_auth_domain_challenge (domain, req);
836 call_handler (SoupMessage *req, SoupClientContext *client)
838 SoupServer *server = client->server;
839 SoupServerHandler *hand;
842 g_signal_emit (server, signals[REQUEST_READ], 0, req, client);
844 if (req->status_code != 0)
847 uri = soup_message_get_uri (req);
848 hand = soup_server_get_handler (server, uri->path);
850 soup_message_set_status (req, SOUP_STATUS_NOT_FOUND);
854 if (hand->callback) {
855 GHashTable *form_data_set;
858 form_data_set = soup_form_decode (uri->query);
860 form_data_set = NULL;
862 /* Call method handler */
863 (*hand->callback) (server, req,
864 uri->path, form_data_set,
865 client, hand->user_data);
868 g_hash_table_destroy (form_data_set);
873 start_request (SoupServer *server, SoupClientContext *client)
875 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
878 soup_client_context_cleanup (client);
880 /* Listen for another request on this connection */
881 msg = g_object_new (SOUP_TYPE_MESSAGE,
882 SOUP_MESSAGE_SERVER_SIDE, TRUE,
886 if (priv->server_header) {
887 soup_message_headers_append (msg->response_headers, "Server",
888 priv->server_header);
891 g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), client);
892 g_signal_connect (msg, "got_body", G_CALLBACK (call_handler), client);
894 g_signal_emit (server, signals[REQUEST_STARTED], 0,
897 g_object_ref (client->sock);
898 soup_message_read_request (msg, client->sock,
899 request_finished, client);
903 socket_disconnected (SoupSocket *sock, SoupClientContext *client)
905 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (client->server);
907 priv->clients = g_slist_remove (priv->clients, client);
908 g_signal_handlers_disconnect_by_func (sock, socket_disconnected, client);
909 g_object_unref (sock);
913 new_connection (SoupSocket *listner, SoupSocket *sock, gpointer user_data)
915 SoupServer *server = user_data;
916 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
917 SoupClientContext *client;
919 client = soup_client_context_new (server, g_object_ref (sock));
920 priv->clients = g_slist_prepend (priv->clients, client);
921 g_signal_connect (sock, "disconnected",
922 G_CALLBACK (socket_disconnected), client);
923 start_request (server, client);
927 * soup_server_run_async:
928 * @server: a #SoupServer
930 * Starts @server, causing it to listen for and process incoming
933 * The server actually runs in @server's #GMainContext. It will not
934 * actually perform any processing unless the appropriate main loop is
935 * running. In the simple case where you did not set the server's
936 * %SOUP_SERVER_ASYNC_CONTEXT property, this means the server will run
937 * whenever the glib main loop is running.
940 soup_server_run_async (SoupServer *server)
942 SoupServerPrivate *priv;
944 g_return_if_fail (SOUP_IS_SERVER (server));
945 priv = SOUP_SERVER_GET_PRIVATE (server);
947 if (!priv->listen_sock) {
949 g_main_loop_unref (priv->loop);
955 g_signal_connect (priv->listen_sock, "new_connection",
956 G_CALLBACK (new_connection), server);
964 * @server: a #SoupServer
966 * Starts @server, causing it to listen for and process incoming
967 * connections. Unlike soup_server_run_async(), this creates a
968 * #GMainLoop and runs it, and it will not return until someone calls
969 * soup_server_quit() to stop the server.
972 soup_server_run (SoupServer *server)
974 SoupServerPrivate *priv;
976 g_return_if_fail (SOUP_IS_SERVER (server));
977 priv = SOUP_SERVER_GET_PRIVATE (server);
980 priv->loop = g_main_loop_new (priv->async_context, TRUE);
981 soup_server_run_async (server);
985 g_main_loop_run (priv->loop);
990 * @server: a #SoupServer
992 * Stops processing for @server. Call this to clean up after
993 * soup_server_run_async(), or to terminate a call to soup_server_run().
995 * @server is still in a working state after this call; you can start
996 * and stop a server as many times as you want.
999 soup_server_quit (SoupServer *server)
1001 SoupServerPrivate *priv;
1003 g_return_if_fail (SOUP_IS_SERVER (server));
1004 priv = SOUP_SERVER_GET_PRIVATE (server);
1006 g_signal_handlers_disconnect_by_func (priv->listen_sock,
1007 G_CALLBACK (new_connection),
1010 g_main_loop_quit (priv->loop);
1014 * soup_server_disconnect:
1015 * @server: a #SoupServer
1017 * Stops processing for @server and closes its socket. This implies
1018 * the effects of soup_server_quit(), but additionally closes the
1019 * listening socket. Note that messages currently in progress will
1020 * continue to be handled, if the main loop associated with the
1021 * server is resumed or kept running.
1023 * After calling this function, @server is no longer functional, so it
1024 * has nearly the same effect as destroying @server entirely. The
1025 * function is thus useful mainly for language bindings without
1026 * explicit control over object lifetime.
1029 soup_server_disconnect (SoupServer *server)
1031 SoupServerPrivate *priv;
1033 g_return_if_fail (SOUP_IS_SERVER (server));
1034 priv = SOUP_SERVER_GET_PRIVATE (server);
1036 soup_server_quit (server);
1038 if (priv->listen_sock) {
1039 soup_socket_disconnect (priv->listen_sock);
1040 g_object_unref (priv->listen_sock);
1041 priv->listen_sock = NULL;
1046 * soup_server_get_async_context:
1047 * @server: a #SoupServer
1049 * Gets @server's async_context. This does not add a ref to the
1050 * context, so you will need to ref it yourself if you want it to
1051 * outlive its server.
1053 * Return value: (transfer none): @server's #GMainContext, which may be %NULL
1056 soup_server_get_async_context (SoupServer *server)
1058 SoupServerPrivate *priv;
1060 g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
1061 priv = SOUP_SERVER_GET_PRIVATE (server);
1063 return priv->async_context;
1067 * SoupClientContext:
1069 * A #SoupClientContext provides additional information about the
1070 * client making a particular request. In particular, you can use
1071 * soup_client_context_get_auth_domain() and
1072 * soup_client_context_get_auth_user() to determine if HTTP
1073 * authentication was used successfully.
1075 * soup_client_context_get_address() and/or
1076 * soup_client_context_get_host() can be used to get information for
1077 * logging or debugging purposes. soup_client_context_get_socket() may
1078 * also be of use in some situations (eg, tracking when multiple
1079 * requests are made on the same connection).
1082 soup_client_context_get_type (void)
1084 static volatile gsize type_volatile = 0;
1086 if (g_once_init_enter (&type_volatile)) {
1087 GType type = g_boxed_type_register_static (
1088 g_intern_static_string ("SoupClientContext"),
1089 (GBoxedCopyFunc) soup_client_context_ref,
1090 (GBoxedFreeFunc) soup_client_context_unref);
1091 g_once_init_leave (&type_volatile, type);
1093 return type_volatile;
1097 * soup_client_context_get_socket:
1098 * @client: a #SoupClientContext
1100 * Retrieves the #SoupSocket that @client is associated with.
1102 * If you are using this method to observe when multiple requests are
1103 * made on the same persistent HTTP connection (eg, as the ntlm-test
1104 * test program does), you will need to pay attention to socket
1105 * destruction as well (either by using weak references, or by
1106 * connecting to the #SoupSocket::disconnected signal), so that you do
1107 * not get fooled when the allocator reuses the memory address of a
1108 * previously-destroyed socket to represent a new socket.
1110 * Return value: (transfer none): the #SoupSocket that @client is
1114 soup_client_context_get_socket (SoupClientContext *client)
1116 g_return_val_if_fail (client != NULL, NULL);
1118 return client->sock;
1122 * soup_client_context_get_address:
1123 * @client: a #SoupClientContext
1125 * Retrieves the #SoupAddress associated with the remote end
1128 * Return value: (transfer none): the #SoupAddress associated with the
1129 * remote end of a connection.
1132 soup_client_context_get_address (SoupClientContext *client)
1134 g_return_val_if_fail (client != NULL, NULL);
1136 return soup_socket_get_remote_address (client->sock);
1140 * soup_client_context_get_host:
1141 * @client: a #SoupClientContext
1143 * Retrieves the IP address associated with the remote end of a
1144 * connection. (If you want the actual hostname, you'll have to call
1145 * soup_client_context_get_address() and then call the appropriate
1146 * #SoupAddress method to resolve it.)
1148 * Return value: the IP address associated with the remote end of a
1152 soup_client_context_get_host (SoupClientContext *client)
1154 SoupAddress *address;
1156 address = soup_client_context_get_address (client);
1157 return soup_address_get_physical (address);
1161 * soup_client_context_get_auth_domain:
1162 * @client: a #SoupClientContext
1164 * Checks whether the request associated with @client has been
1165 * authenticated, and if so returns the #SoupAuthDomain that
1168 * Return value: (transfer none) (allow-none): a #SoupAuthDomain, or
1169 * %NULL if the request was not authenticated.
1172 soup_client_context_get_auth_domain (SoupClientContext *client)
1174 g_return_val_if_fail (client != NULL, NULL);
1176 return client->auth_domain;
1180 * soup_client_context_get_auth_user:
1181 * @client: a #SoupClientContext
1183 * Checks whether the request associated with @client has been
1184 * authenticated, and if so returns the username that the client
1187 * Return value: the authenticated-as user, or %NULL if the request
1188 * was not authenticated.
1191 soup_client_context_get_auth_user (SoupClientContext *client)
1193 g_return_val_if_fail (client != NULL, NULL);
1195 return client->auth_user;
1199 * SoupServerCallback:
1200 * @server: the #SoupServer
1201 * @msg: the message being processed
1202 * @path: the path component of @msg's Request-URI
1203 * @query: (element-type utf8 utf8) (allow-none): the parsed query
1204 * component of @msg's Request-URI
1205 * @client: additional contextual information about the client
1206 * @user_data: the data passed to @soup_server_add_handler
1208 * A callback used to handle requests to a #SoupServer. The callback
1209 * will be invoked after receiving the request body; @msg's %method,
1210 * %request_headers, and %request_body fields will be filled in.
1212 * @path and @query contain the likewise-named components of the
1213 * Request-URI, subject to certain assumptions. By default,
1214 * #SoupServer decodes all percent-encoding in the URI path, such that
1215 * "/foo%<!-- -->2Fbar" is treated the same as "/foo/bar". If your
1216 * server is serving resources in some non-POSIX-filesystem namespace,
1217 * you may want to distinguish those as two distinct paths. In that
1218 * case, you can set the %SOUP_SERVER_RAW_PATHS property when creating
1219 * the #SoupServer, and it will leave those characters undecoded. (You
1220 * may want to call soup_uri_normalize() to decode any percent-encoded
1221 * characters that you aren't handling specially.)
1223 * @query contains the query component of the Request-URI parsed
1224 * according to the rules for HTML form handling. Although this is the
1225 * only commonly-used query string format in HTTP, there is nothing
1226 * that actually requires that HTTP URIs use that format; if your
1227 * server needs to use some other format, you can just ignore @query,
1228 * and call soup_message_get_uri() and parse the URI's query field
1231 * After determining what to do with the request, the callback must at
1232 * a minimum call soup_message_set_status() (or
1233 * soup_message_set_status_full()) on @msg to set the response status
1234 * code. Additionally, it may set response headers and/or fill in the
1237 * If the callback cannot fully fill in the response before returning
1238 * (eg, if it needs to wait for information from a database, or
1239 * another network server), it should call soup_server_pause_message()
1240 * to tell #SoupServer to not send the response right away. When the
1241 * response is ready, call soup_server_unpause_message() to cause it
1244 * To send the response body a bit at a time using "chunked" encoding,
1245 * first call soup_message_headers_set_encoding() to set
1246 * %SOUP_ENCODING_CHUNKED on the %response_headers. Then call
1247 * soup_message_body_append() (or soup_message_body_append_buffer())
1248 * to append each chunk as it becomes ready, and
1249 * soup_server_unpause_message() to make sure it's running. (The
1250 * server will automatically pause the message if it is using chunked
1251 * encoding but no more chunks are available.) When you are done, call
1252 * soup_message_body_complete() to indicate that no more chunks are
1257 * soup_server_add_handler:
1258 * @server: a #SoupServer
1259 * @path: (allow-none): the toplevel path for the handler
1260 * @callback: callback to invoke for requests under @path
1261 * @user_data: data for @callback
1262 * @destroy: destroy notifier to free @user_data
1264 * Adds a handler to @server for requests under @path. See the
1265 * documentation for #SoupServerCallback for information about
1266 * how callbacks should behave.
1268 * If @path is %NULL or "/", then this will be the default handler for
1269 * all requests that don't have a more specific handler. Note though
1270 * that if you want to handle requests to the special "*" URI, you
1271 * must explicitly register a handler for "*"; the default handler
1272 * will not be used for that case.
1275 soup_server_add_handler (SoupServer *server,
1277 SoupServerCallback callback,
1279 GDestroyNotify destroy)
1281 SoupServerPrivate *priv;
1282 SoupServerHandler *hand;
1284 g_return_if_fail (SOUP_IS_SERVER (server));
1285 g_return_if_fail (callback != NULL);
1286 priv = SOUP_SERVER_GET_PRIVATE (server);
1288 /* "" was never documented as meaning the same this as "/",
1289 * but it effectively was. We have to special case it now or
1290 * otherwise it would match "*" too.
1292 if (path && (!*path || !strcmp (path, "/")))
1295 hand = g_slice_new0 (SoupServerHandler);
1296 hand->path = g_strdup (path);
1297 hand->callback = callback;
1298 hand->destroy = destroy;
1299 hand->user_data = user_data;
1301 soup_server_remove_handler (server, path);
1303 soup_path_map_add (priv->handlers, path, hand);
1305 priv->default_handler = hand;
1309 unregister_handler (SoupServerHandler *handler)
1311 if (handler->destroy)
1312 handler->destroy (handler->user_data);
1316 * soup_server_remove_handler:
1317 * @server: a #SoupServer
1318 * @path: the toplevel path for the handler
1320 * Removes the handler registered at @path.
1323 soup_server_remove_handler (SoupServer *server, const char *path)
1325 SoupServerPrivate *priv;
1326 SoupServerHandler *hand;
1328 g_return_if_fail (SOUP_IS_SERVER (server));
1329 priv = SOUP_SERVER_GET_PRIVATE (server);
1331 if (!path || !*path || !strcmp (path, "/")) {
1332 if (priv->default_handler) {
1333 unregister_handler (priv->default_handler);
1334 free_handler (priv->default_handler);
1335 priv->default_handler = NULL;
1340 hand = soup_path_map_lookup (priv->handlers, path);
1341 if (hand && !strcmp (path, hand->path)) {
1342 unregister_handler (hand);
1343 soup_path_map_remove (priv->handlers, path);
1348 * soup_server_add_auth_domain:
1349 * @server: a #SoupServer
1350 * @auth_domain: a #SoupAuthDomain
1352 * Adds an authentication domain to @server. Each auth domain will
1353 * have the chance to require authentication for each request that
1354 * comes in; normally auth domains will require authentication for
1355 * requests on certain paths that they have been set up to watch, or
1356 * that meet other criteria set by the caller. If an auth domain
1357 * determines that a request requires authentication (and the request
1358 * doesn't contain authentication), @server will automatically reject
1359 * the request with an appropriate status (401 Unauthorized or 407
1360 * Proxy Authentication Required). If the request used the
1361 * "100-continue" Expectation, @server will reject it before the
1362 * request body is sent.
1365 soup_server_add_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain)
1367 SoupServerPrivate *priv;
1369 g_return_if_fail (SOUP_IS_SERVER (server));
1370 priv = SOUP_SERVER_GET_PRIVATE (server);
1372 priv->auth_domains = g_slist_append (priv->auth_domains, auth_domain);
1373 g_object_ref (auth_domain);
1377 * soup_server_remove_auth_domain:
1378 * @server: a #SoupServer
1379 * @auth_domain: a #SoupAuthDomain
1381 * Removes @auth_domain from @server.
1384 soup_server_remove_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain)
1386 SoupServerPrivate *priv;
1388 g_return_if_fail (SOUP_IS_SERVER (server));
1389 priv = SOUP_SERVER_GET_PRIVATE (server);
1391 priv->auth_domains = g_slist_remove (priv->auth_domains, auth_domain);
1392 g_object_unref (auth_domain);
1396 * soup_server_pause_message:
1397 * @server: a #SoupServer
1398 * @msg: a #SoupMessage associated with @server.
1400 * Pauses I/O on @msg. This can be used when you need to return from
1401 * the server handler without having the full response ready yet. Use
1402 * soup_server_unpause_message() to resume I/O.
1405 soup_server_pause_message (SoupServer *server,
1408 g_return_if_fail (SOUP_IS_SERVER (server));
1409 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1411 soup_message_io_pause (msg);
1415 * soup_server_unpause_message:
1416 * @server: a #SoupServer
1417 * @msg: a #SoupMessage associated with @server.
1419 * Resumes I/O on @msg. Use this to resume after calling
1420 * soup_server_pause_message(), or after adding a new chunk to a
1423 * I/O won't actually resume until you return to the main loop.
1426 soup_server_unpause_message (SoupServer *server,
1429 g_return_if_fail (SOUP_IS_SERVER (server));
1430 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1432 soup_message_io_unpause (msg);