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.
14 #include "soup-server.h"
16 #include "soup-message-private.h"
17 #include "soup-misc-private.h"
18 #include "soup-path-map.h"
22 * @short_description: HTTP server
23 * @see_also: #SoupAuthDomain
25 * #SoupServer implements a simple HTTP server.
27 * To begin, create a server using soup_server_new(). Add at least one
28 * handler by calling soup_server_add_handler(); the handler will be
29 * called to process any requests underneath the path passed to
30 * soup_server_add_handler(). (If you want all requests to go to the
31 * same handler, just pass "/" (or %NULL) for the path.) Any request
32 * that does not match any handler will automatically be returned to
33 * the client with a 404 (Not Found) status.
35 * If you want to handle the special "*" URI (eg, "OPTIONS *"), you
36 * must explicitly register a handler for "*"; the default handler
37 * will not be used for that case.
39 * To add authentication to some or all paths, create an appropriate
40 * #SoupAuthDomain (qv), and add it to the server via
41 * soup_server_add_auth_domain(). (As with handlers, you must
42 * explicitly add "*" to an auth domain if you want it to be covered.)
44 * Additional processing options are available via #SoupServer's
45 * signals; Connect to #SoupServer::request-started to be notified
46 * every time a new request is being processed. (This gives you a
47 * chance to connect to the #SoupMessage "got-" signals in case you
48 * want to do processing before the body has been fully read.)
50 * Once the server is set up, start it processing connections by
51 * calling soup_server_run_async() or soup_server_run(). #SoupServer
52 * runs via the glib main loop; if you need to have a server that runs
53 * in another thread (or merely isn't bound to the default main loop),
54 * create a #GMainContext for it to use, and set that via the
55 * #SOUP_SERVER_ASYNC_CONTEXT property.
58 G_DEFINE_TYPE (SoupServer, soup_server, G_TYPE_OBJECT)
68 static guint signals[LAST_SIGNAL] = { 0 };
70 struct SoupClientContext {
74 SoupAuthDomain *auth_domain;
83 SoupServerCallback callback;
84 GDestroyNotify destroy;
92 char *ssl_cert_file, *ssl_key_file;
93 GTlsCertificate *ssl_cert;
99 SoupSocket *listen_sock;
103 SoupPathMap *handlers;
104 SoupServerHandler *default_handler;
106 GSList *auth_domains;
108 GMainContext *async_context;
110 char **http_aliases, **https_aliases;
112 #define SOUP_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SERVER, SoupServerPrivate))
114 #define SOUP_SERVER_SERVER_HEADER_BASE "libsoup/" PACKAGE_VERSION
123 PROP_TLS_CERTIFICATE,
133 static SoupClientContext *soup_client_context_ref (SoupClientContext *client);
134 static void soup_client_context_unref (SoupClientContext *client);
137 free_handler (SoupServerHandler *hand)
140 g_slice_free (SoupServerHandler, hand);
144 soup_server_init (SoupServer *server)
146 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
148 priv->handlers = soup_path_map_new ((GDestroyNotify)free_handler);
150 priv->http_aliases = g_new (char *, 2);
151 priv->http_aliases[0] = (char *)g_intern_string ("*");
152 priv->http_aliases[1] = NULL;
156 soup_server_finalize (GObject *object)
158 SoupServer *server = SOUP_SERVER (object);
159 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
161 g_clear_object (&priv->iface);
163 g_free (priv->ssl_cert_file);
164 g_free (priv->ssl_key_file);
165 g_clear_object (&priv->ssl_cert);
167 g_free (priv->server_header);
169 g_clear_object (&priv->listen_sock);
171 while (priv->clients) {
172 SoupClientContext *client = priv->clients->data;
173 SoupSocket *sock = g_object_ref (client->sock);
175 priv->clients = g_slist_remove (priv->clients, client);
177 /* keep a ref on the client context so it doesn't get destroyed
178 * when we finish the message; the SoupSocket::disconnect
179 * handler will refer to client->server later when the socket is
182 soup_client_context_ref (client);
185 soup_message_set_status (client->msg, SOUP_STATUS_IO_ERROR);
186 soup_message_io_finished (client->msg);
189 soup_socket_disconnect (sock);
190 g_object_unref (sock);
192 soup_client_context_unref (client);
195 g_clear_pointer (&priv->default_handler, free_handler);
196 soup_path_map_free (priv->handlers);
198 g_slist_free_full (priv->auth_domains, g_object_unref);
200 g_clear_pointer (&priv->loop, g_main_loop_unref);
201 g_clear_pointer (&priv->async_context, g_main_context_unref);
203 g_free (priv->http_aliases);
204 g_free (priv->https_aliases);
206 G_OBJECT_CLASS (soup_server_parent_class)->finalize (object);
210 soup_server_constructor (GType type,
211 guint n_construct_properties,
212 GObjectConstructParam *construct_properties)
215 SoupServerPrivate *priv;
217 server = G_OBJECT_CLASS (soup_server_parent_class)->constructor (
218 type, n_construct_properties, construct_properties);
221 priv = SOUP_SERVER_GET_PRIVATE (server);
225 soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4,
229 if (priv->ssl_cert_file && priv->ssl_key_file) {
230 GError *error = NULL;
233 g_object_unref (priv->ssl_cert);
234 priv->ssl_cert = g_tls_certificate_new_from_files (priv->ssl_cert_file, priv->ssl_key_file, &error);
235 if (!priv->ssl_cert) {
236 g_warning ("Could not read SSL certificate from '%s': %s",
237 priv->ssl_cert_file, error->message);
238 g_error_free (error);
239 g_object_unref (server);
245 soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, priv->iface,
246 SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_cert,
247 SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
249 if (!soup_socket_listen (priv->listen_sock)) {
250 g_object_unref (server);
254 /* Re-resolve the interface address, in particular in case
255 * the passed-in address had SOUP_ADDRESS_ANY_PORT.
257 g_object_unref (priv->iface);
258 priv->iface = soup_socket_get_local_address (priv->listen_sock);
259 g_object_ref (priv->iface);
260 priv->port = soup_address_get_port (priv->iface);
265 /* priv->http_aliases and priv->https_aliases are stored as arrays of
266 * *interned* strings, so we can't just use g_strdupv() to set them.
269 set_aliases (char ***variable, char **value)
281 len = g_strv_length (value);
282 *variable = g_new (char *, len + 1);
283 for (i = 0; i < len; i++)
284 (*variable)[i] = (char *)g_intern_string (value[i]);
285 (*variable)[i] = NULL;
289 soup_server_set_property (GObject *object, guint prop_id,
290 const GValue *value, GParamSpec *pspec)
292 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (object);
297 priv->port = g_value_get_uint (value);
301 g_object_unref (priv->iface);
302 priv->iface = g_value_get_object (value);
304 g_object_ref (priv->iface);
306 case PROP_SSL_CERT_FILE:
307 priv->ssl_cert_file =
308 g_strdup (g_value_get_string (value));
310 case PROP_SSL_KEY_FILE:
312 g_strdup (g_value_get_string (value));
314 case PROP_TLS_CERTIFICATE:
316 g_object_unref (priv->ssl_cert);
317 priv->ssl_cert = g_value_dup_object (value);
319 case PROP_ASYNC_CONTEXT:
320 priv->async_context = g_value_get_pointer (value);
321 if (priv->async_context)
322 g_main_context_ref (priv->async_context);
325 priv->raw_paths = g_value_get_boolean (value);
327 case PROP_SERVER_HEADER:
328 g_free (priv->server_header);
329 header = g_value_get_string (value);
331 priv->server_header = NULL;
333 priv->server_header =
334 g_strdup (SOUP_SERVER_SERVER_HEADER_BASE);
335 } else if (g_str_has_suffix (header, " ")) {
336 priv->server_header =
337 g_strdup_printf ("%s%s", header,
338 SOUP_SERVER_SERVER_HEADER_BASE);
340 priv->server_header = g_strdup (header);
342 case PROP_HTTP_ALIASES:
343 set_aliases (&priv->http_aliases, g_value_get_boxed (value));
345 case PROP_HTTPS_ALIASES:
346 set_aliases (&priv->https_aliases, g_value_get_boxed (value));
349 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
355 soup_server_get_property (GObject *object, guint prop_id,
356 GValue *value, GParamSpec *pspec)
358 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (object);
362 g_value_set_uint (value, priv->port);
365 g_value_set_object (value, priv->iface);
367 case PROP_SSL_CERT_FILE:
368 g_value_set_string (value, priv->ssl_cert_file);
370 case PROP_SSL_KEY_FILE:
371 g_value_set_string (value, priv->ssl_key_file);
373 case PROP_TLS_CERTIFICATE:
374 g_value_set_object (value, priv->ssl_cert);
376 case PROP_ASYNC_CONTEXT:
377 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
380 g_value_set_boolean (value, priv->raw_paths);
382 case PROP_SERVER_HEADER:
383 g_value_set_string (value, priv->server_header);
385 case PROP_HTTP_ALIASES:
386 g_value_set_boxed (value, priv->http_aliases);
388 case PROP_HTTPS_ALIASES:
389 g_value_set_boxed (value, priv->https_aliases);
392 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
398 soup_server_class_init (SoupServerClass *server_class)
400 GObjectClass *object_class = G_OBJECT_CLASS (server_class);
402 g_type_class_add_private (server_class, sizeof (SoupServerPrivate));
404 /* virtual method override */
405 object_class->constructor = soup_server_constructor;
406 object_class->finalize = soup_server_finalize;
407 object_class->set_property = soup_server_set_property;
408 object_class->get_property = soup_server_get_property;
413 * SoupServer::request-started:
414 * @server: the server
415 * @message: the new message
416 * @client: the client context
418 * Emitted when the server has started reading a new request.
419 * @message will be completely blank; not even the
420 * Request-Line will have been read yet. About the only thing
421 * you can usefully do with it is connect to its signals.
423 * If the request is read successfully, this will eventually
424 * be followed by a #SoupServer::request_read signal. If a
425 * response is then sent, the request processing will end with
426 * a #SoupServer::request_finished signal. If a network error
427 * occurs, the processing will instead end with
428 * #SoupServer::request_aborted.
430 signals[REQUEST_STARTED] =
431 g_signal_new ("request-started",
432 G_OBJECT_CLASS_TYPE (object_class),
434 G_STRUCT_OFFSET (SoupServerClass, request_started),
439 SOUP_TYPE_CLIENT_CONTEXT);
442 * SoupServer::request-read:
443 * @server: the server
444 * @message: the message
445 * @client: the client context
447 * Emitted when the server has successfully read a request.
448 * @message will have all of its request-side information
449 * filled in, and if the message was authenticated, @client
450 * will have information about that. This signal is emitted
451 * before any handlers are called for the message, and if it
452 * sets the message's #status_code, then normal handler
453 * processing will be skipped.
455 signals[REQUEST_READ] =
456 g_signal_new ("request-read",
457 G_OBJECT_CLASS_TYPE (object_class),
459 G_STRUCT_OFFSET (SoupServerClass, request_read),
464 SOUP_TYPE_CLIENT_CONTEXT);
467 * SoupServer::request-finished:
468 * @server: the server
469 * @message: the message
470 * @client: the client context
472 * Emitted when the server has finished writing a response to
475 signals[REQUEST_FINISHED] =
476 g_signal_new ("request-finished",
477 G_OBJECT_CLASS_TYPE (object_class),
479 G_STRUCT_OFFSET (SoupServerClass, request_finished),
484 SOUP_TYPE_CLIENT_CONTEXT);
487 * SoupServer::request-aborted:
488 * @server: the server
489 * @message: the message
490 * @client: the client context
492 * Emitted when processing has failed for a message; this
493 * could mean either that it could not be read (if
494 * #SoupServer::request_read has not been emitted for it yet),
495 * or that the response could not be written back (if
496 * #SoupServer::request_read has been emitted but
497 * #SoupServer::request_finished has not been).
499 * @message is in an undefined state when this signal is
500 * emitted; the signal exists primarily to allow the server to
501 * free any state that it may have allocated in
502 * #SoupServer::request_started.
504 signals[REQUEST_ABORTED] =
505 g_signal_new ("request-aborted",
506 G_OBJECT_CLASS_TYPE (object_class),
508 G_STRUCT_OFFSET (SoupServerClass, request_aborted),
513 SOUP_TYPE_CLIENT_CONTEXT);
519 * Alias for the #SoupServer:port property. (The port the
520 * server listens on.)
522 g_object_class_install_property (
523 object_class, PROP_PORT,
524 g_param_spec_uint (SOUP_SERVER_PORT,
528 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
530 * SOUP_SERVER_INTERFACE:
532 * Alias for the #SoupServer:interface property. (The address
533 * of the network interface the server listens on.)
535 g_object_class_install_property (
536 object_class, PROP_INTERFACE,
537 g_param_spec_object (SOUP_SERVER_INTERFACE,
539 "Address of interface to listen on",
541 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
543 * SOUP_SERVER_SSL_CERT_FILE:
545 * Alias for the #SoupServer:ssl-cert-file property, qv.
548 * SoupServer:ssl-cert-file:
550 * Path to a file containing a PEM-encoded certificate. If
551 * this and #SoupServer:ssl-key-file are both set, then the
552 * server will speak https rather than plain http.
554 * Alternatively, you can use #SoupServer:tls-certificate
555 * to provide an arbitrary #GTlsCertificate.
557 g_object_class_install_property (
558 object_class, PROP_SSL_CERT_FILE,
559 g_param_spec_string (SOUP_SERVER_SSL_CERT_FILE,
560 "SSL certificate file",
561 "File containing server SSL certificate",
563 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
565 * SOUP_SERVER_SSL_KEY_FILE:
567 * Alias for the #SoupServer:ssl-key-file property, qv.
570 * SoupServer:ssl-key-file:
572 * Path to a file containing a PEM-encoded private key. If
573 * this and #SoupServer:ssl-key-file are both set, then the
574 * server will speak https rather than plain http. Note that
575 * you are allowed to set them to the same value, if you have
576 * a single file containing both the certificate and the key.
578 * Alternatively, you can use #SoupServer:tls-certificate
579 * to provide an arbitrary #GTlsCertificate.
581 g_object_class_install_property (
582 object_class, PROP_SSL_KEY_FILE,
583 g_param_spec_string (SOUP_SERVER_SSL_KEY_FILE,
585 "File containing server SSL key",
587 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
589 * SOUP_SERVER_TLS_CERTIFICATE:
591 * Alias for the #SoupServer:tls-certificate property, qv.
594 * SoupServer:tls-certificate:
596 * A #GTlsCertificate that has a #GTlsCertificate:private-key
597 * set. If this is set, then the server will speak https
598 * rather than plain http.
600 * Alternatively, you can use #SoupServer:ssl-cert-file and
601 * #SoupServer:ssl-key-file properties, to have #SoupServer
602 * read in a a certificate from a file.
604 g_object_class_install_property (
605 object_class, PROP_TLS_CERTIFICATE,
606 g_param_spec_object (SOUP_SERVER_TLS_CERTIFICATE,
608 "GTlsCertificate to use for https",
609 G_TYPE_TLS_CERTIFICATE,
610 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
612 * SOUP_SERVER_ASYNC_CONTEXT:
614 * Alias for the #SoupServer:async-context property. (The
615 * server's #GMainContext.)
617 g_object_class_install_property (
618 object_class, PROP_ASYNC_CONTEXT,
619 g_param_spec_pointer (SOUP_SERVER_ASYNC_CONTEXT,
620 "Async GMainContext",
621 "The GMainContext to dispatch async I/O in",
622 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
624 * SOUP_SERVER_RAW_PATHS:
626 * Alias for the #SoupServer:raw-paths property. (If %TRUE,
627 * percent-encoding in the Request-URI path will not be
628 * automatically decoded.)
630 g_object_class_install_property (
631 object_class, PROP_RAW_PATHS,
632 g_param_spec_boolean (SOUP_SERVER_RAW_PATHS,
634 "If %TRUE, percent-encoding in the Request-URI path will not be automatically decoded.",
636 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
639 * SoupServer:server-header:
641 * If non-%NULL, the value to use for the "Server" header on
642 * #SoupMessage<!-- -->s processed by this server.
644 * The Server header is the server equivalent of the
645 * User-Agent header, and provides information about the
646 * server and its components. It contains a list of one or
647 * more product tokens, separated by whitespace, with the most
648 * significant product token coming first. The tokens must be
649 * brief, ASCII, and mostly alphanumeric (although "-", "_",
650 * and "." are also allowed), and may optionally include a "/"
651 * followed by a version string. You may also put comments,
652 * enclosed in parentheses, between or after the tokens.
654 * Some HTTP server implementations intentionally do not use
655 * version numbers in their Server header, so that
656 * installations running older versions of the server don't
657 * end up advertising their vulnerability to specific security
660 * As with #SoupSession:user_agent, if you set a
661 * #SoupServer:server_header property that has trailing whitespace,
662 * #SoupServer will append its own product token (eg,
663 * "<literal>libsoup/2.3.2</literal>") to the end of the
667 * SOUP_SERVER_SERVER_HEADER:
669 * Alias for the #SoupServer:server-header property, qv.
671 g_object_class_install_property (
672 object_class, PROP_SERVER_HEADER,
673 g_param_spec_string (SOUP_SERVER_SERVER_HEADER,
677 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
680 * SoupServer:http-aliases:
682 * A %NULL-terminated array of URI schemes that should be
683 * considered to be aliases for "http". Eg, if this included
684 * <literal>"dav"</literal>, than a URI of
685 * <literal>dav://example.com/path</literal> would be treated
686 * identically to <literal>http://example.com/path</literal>.
687 * In particular, this is needed in cases where a client
688 * sends requests with absolute URIs, where those URIs do
691 * The default value is an array containing the single element
692 * <literal>"*"</literal>, a special value which means that
693 * any scheme except "https" is considered to be an alias for
696 * See also #SoupServer:https-aliases.
701 * SOUP_SERVERI_HTTP_ALIASES:
703 * Alias for the #SoupServer:http-aliases property, qv.
707 g_object_class_install_property (
708 object_class, PROP_HTTP_ALIASES,
709 g_param_spec_boxed (SOUP_SERVER_HTTP_ALIASES,
711 "URI schemes that are considered aliases for 'http'",
715 * SoupServer:https-aliases:
717 * A comma-delimited list of URI schemes that should be
718 * considered to be aliases for "https". See
719 * #SoupServer:http-aliases for more information.
721 * The default value is %NULL, meaning that no URI schemes
722 * are considered aliases for "https".
727 * SOUP_SERVER_HTTPS_ALIASES:
729 * Alias for the #SoupServer:https-aliases property, qv.
733 g_object_class_install_property (
734 object_class, PROP_HTTPS_ALIASES,
735 g_param_spec_boxed (SOUP_SERVER_HTTPS_ALIASES,
737 "URI schemes that are considered aliases for 'https'",
744 * @optname1: name of first property to set
745 * @...: value of @optname1, followed by additional property/value pairs
747 * Creates a new #SoupServer.
749 * Return value: a new #SoupServer
752 soup_server_new (const char *optname1, ...)
757 va_start (ap, optname1);
758 server = (SoupServer *)g_object_new_valist (SOUP_TYPE_SERVER,
766 * soup_server_get_port:
767 * @server: a #SoupServer
769 * Gets the TCP port that @server is listening on. This is most useful
770 * when you did not request a specific port (or explicitly requested
771 * %SOUP_ADDRESS_ANY_PORT).
773 * Return value: the port @server is listening on.
776 soup_server_get_port (SoupServer *server)
778 g_return_val_if_fail (SOUP_IS_SERVER (server), 0);
780 return SOUP_SERVER_GET_PRIVATE (server)->port;
784 * soup_server_is_https:
785 * @server: a #SoupServer
787 * Checks whether @server is running plain http or https.
789 * In order for a server to run https, you must set the
790 * %SOUP_SERVER_SSL_CERT_FILE and %SOUP_SERVER_SSL_KEY_FILE properties
791 * or %SOUP_SERVER_TLS_CERTIFICATE property to provide it with an SSL
792 * certificate to use.
794 * Return value: %TRUE if @server is serving https.
797 soup_server_is_https (SoupServer *server)
799 SoupServerPrivate *priv;
801 g_return_val_if_fail (SOUP_IS_SERVER (server), 0);
802 priv = SOUP_SERVER_GET_PRIVATE (server);
804 return priv->ssl_cert != NULL;
808 * soup_server_get_listener:
809 * @server: a #SoupServer
811 * Gets @server's listening socket. You should treat this as
812 * read-only; writing to it or modifiying it may cause @server to
815 * Return value: (transfer none): the listening socket.
818 soup_server_get_listener (SoupServer *server)
820 SoupServerPrivate *priv;
822 g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
823 priv = SOUP_SERVER_GET_PRIVATE (server);
825 return priv->listen_sock;
828 static void start_request (SoupServer *, SoupClientContext *);
830 static SoupClientContext *
831 soup_client_context_new (SoupServer *server, SoupSocket *sock)
833 SoupClientContext *client = g_slice_new0 (SoupClientContext);
835 client->server = server;
837 client->ref_count = 1;
843 soup_client_context_cleanup (SoupClientContext *client)
845 if (client->auth_domain) {
846 g_object_unref (client->auth_domain);
847 client->auth_domain = NULL;
849 if (client->auth_user) {
850 g_free (client->auth_user);
851 client->auth_user = NULL;
856 static SoupClientContext *
857 soup_client_context_ref (SoupClientContext *client)
864 soup_client_context_unref (SoupClientContext *client)
866 if (--client->ref_count == 0) {
867 soup_client_context_cleanup (client);
868 g_slice_free (SoupClientContext, client);
873 request_finished (SoupMessage *msg, gpointer user_data)
875 SoupClientContext *client = user_data;
876 SoupServer *server = client->server;
877 SoupSocket *sock = client->sock;
879 soup_message_finished (msg);
880 g_signal_emit (server,
881 msg->status_code == SOUP_STATUS_IO_ERROR ?
882 signals[REQUEST_ABORTED] : signals[REQUEST_FINISHED],
885 soup_client_context_cleanup (client);
886 if (soup_socket_is_connected (sock) && soup_message_is_keepalive (msg)) {
887 /* Start a new request */
888 start_request (server, client);
890 soup_socket_disconnect (sock);
891 soup_client_context_unref (client);
893 g_object_unref (msg);
894 g_object_unref (sock);
897 static SoupServerHandler *
898 soup_server_get_handler (SoupServer *server, const char *path)
900 SoupServerPrivate *priv;
901 SoupServerHandler *hand;
903 g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
904 priv = SOUP_SERVER_GET_PRIVATE (server);
907 hand = soup_path_map_lookup (priv->handlers, path);
910 if (!strcmp (path, "*"))
913 return priv->default_handler;
917 got_headers (SoupMessage *msg, SoupClientContext *client)
919 SoupServer *server = client->server;
920 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
924 SoupAuthDomain *domain;
926 gboolean rejected = FALSE;
929 uri = soup_message_get_uri (msg);
930 if ((soup_server_is_https (server) && !soup_uri_is_https (uri, priv->https_aliases)) ||
931 (!soup_server_is_https (server) && !soup_uri_is_http (uri, priv->http_aliases))) {
932 soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
936 if (!priv->raw_paths) {
939 decoded_path = soup_uri_decode (uri->path);
941 if (strstr (decoded_path, "/../") ||
942 g_str_has_suffix (decoded_path, "/..")) {
943 /* Introducing new ".." segments is not allowed */
944 g_free (decoded_path);
945 soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
949 soup_uri_set_path (uri, decoded_path);
950 g_free (decoded_path);
953 /* Add required response headers */
954 date = soup_date_new_from_now (0);
955 date_string = soup_date_to_string (date, SOUP_DATE_HTTP);
956 soup_message_headers_replace (msg->response_headers, "Date",
958 g_free (date_string);
959 soup_date_free (date);
961 /* Now handle authentication. (We do this here so that if
962 * the request uses "Expect: 100-continue", we can reject it
963 * immediately rather than waiting for the request body to
966 for (iter = priv->auth_domains; iter; iter = iter->next) {
969 if (soup_auth_domain_covers (domain, msg)) {
970 auth_user = soup_auth_domain_accepts (domain, msg);
972 client->auth_domain = g_object_ref (domain);
973 client->auth_user = auth_user;
981 /* If no auth domain rejected it, then it's ok. */
985 for (iter = priv->auth_domains; iter; iter = iter->next) {
988 if (soup_auth_domain_covers (domain, msg))
989 soup_auth_domain_challenge (domain, msg);
994 call_handler (SoupMessage *msg, SoupClientContext *client)
996 SoupServer *server = client->server;
997 SoupServerHandler *hand;
1000 g_signal_emit (server, signals[REQUEST_READ], 0, msg, client);
1002 if (msg->status_code != 0)
1005 uri = soup_message_get_uri (msg);
1006 hand = soup_server_get_handler (server, uri->path);
1008 soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
1012 if (hand->callback) {
1013 GHashTable *form_data_set;
1016 form_data_set = soup_form_decode (uri->query);
1018 form_data_set = NULL;
1020 /* Call method handler */
1021 (*hand->callback) (server, msg,
1022 uri->path, form_data_set,
1023 client, hand->user_data);
1026 g_hash_table_unref (form_data_set);
1031 start_request (SoupServer *server, SoupClientContext *client)
1033 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
1036 soup_client_context_cleanup (client);
1038 /* Listen for another request on this connection */
1039 msg = g_object_new (SOUP_TYPE_MESSAGE,
1040 SOUP_MESSAGE_SERVER_SIDE, TRUE,
1044 if (priv->server_header) {
1045 soup_message_headers_append (msg->response_headers, "Server",
1046 priv->server_header);
1049 g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), client);
1050 g_signal_connect (msg, "got_body", G_CALLBACK (call_handler), client);
1052 g_signal_emit (server, signals[REQUEST_STARTED], 0,
1055 g_object_ref (client->sock);
1057 if (priv->async_context)
1058 g_main_context_push_thread_default (priv->async_context);
1059 soup_message_read_request (msg, client->sock,
1060 request_finished, client);
1061 if (priv->async_context)
1062 g_main_context_pop_thread_default (priv->async_context);
1066 socket_disconnected (SoupSocket *sock, SoupClientContext *client)
1068 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (client->server);
1070 priv->clients = g_slist_remove (priv->clients, client);
1071 g_signal_handlers_disconnect_by_func (sock, socket_disconnected, client);
1072 g_object_unref (sock);
1076 new_connection (SoupSocket *listner, SoupSocket *sock, gpointer user_data)
1078 SoupServer *server = user_data;
1079 SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
1080 SoupClientContext *client;
1082 client = soup_client_context_new (server, g_object_ref (sock));
1083 priv->clients = g_slist_prepend (priv->clients, client);
1084 g_signal_connect (sock, "disconnected",
1085 G_CALLBACK (socket_disconnected), client);
1086 start_request (server, client);
1090 * soup_server_run_async:
1091 * @server: a #SoupServer
1093 * Starts @server, causing it to listen for and process incoming
1096 * The server actually runs in @server's #GMainContext. It will not
1097 * actually perform any processing unless the appropriate main loop is
1098 * running. In the simple case where you did not set the server's
1099 * %SOUP_SERVER_ASYNC_CONTEXT property, this means the server will run
1100 * whenever the glib main loop is running.
1103 soup_server_run_async (SoupServer *server)
1105 SoupServerPrivate *priv;
1107 g_return_if_fail (SOUP_IS_SERVER (server));
1108 priv = SOUP_SERVER_GET_PRIVATE (server);
1110 if (!priv->listen_sock) {
1112 g_main_loop_unref (priv->loop);
1118 g_signal_connect (priv->listen_sock, "new_connection",
1119 G_CALLBACK (new_connection), server);
1127 * @server: a #SoupServer
1129 * Starts @server, causing it to listen for and process incoming
1130 * connections. Unlike soup_server_run_async(), this creates a
1131 * #GMainLoop and runs it, and it will not return until someone calls
1132 * soup_server_quit() to stop the server.
1135 soup_server_run (SoupServer *server)
1137 SoupServerPrivate *priv;
1139 g_return_if_fail (SOUP_IS_SERVER (server));
1140 priv = SOUP_SERVER_GET_PRIVATE (server);
1143 priv->loop = g_main_loop_new (priv->async_context, TRUE);
1144 soup_server_run_async (server);
1148 g_main_loop_run (priv->loop);
1153 * @server: a #SoupServer
1155 * Stops processing for @server. Call this to clean up after
1156 * soup_server_run_async(), or to terminate a call to soup_server_run().
1158 * @server is still in a working state after this call; you can start
1159 * and stop a server as many times as you want.
1162 soup_server_quit (SoupServer *server)
1164 SoupServerPrivate *priv;
1166 g_return_if_fail (SOUP_IS_SERVER (server));
1167 priv = SOUP_SERVER_GET_PRIVATE (server);
1169 g_signal_handlers_disconnect_by_func (priv->listen_sock,
1170 G_CALLBACK (new_connection),
1173 g_main_loop_quit (priv->loop);
1177 * soup_server_disconnect:
1178 * @server: a #SoupServer
1180 * Stops processing for @server and closes its socket. This implies
1181 * the effects of soup_server_quit(), but additionally closes the
1182 * listening socket. Note that messages currently in progress will
1183 * continue to be handled, if the main loop associated with the
1184 * server is resumed or kept running.
1186 * After calling this function, @server is no longer functional, so it
1187 * has nearly the same effect as destroying @server entirely. The
1188 * function is thus useful mainly for language bindings without
1189 * explicit control over object lifetime.
1192 soup_server_disconnect (SoupServer *server)
1194 SoupServerPrivate *priv;
1196 g_return_if_fail (SOUP_IS_SERVER (server));
1197 priv = SOUP_SERVER_GET_PRIVATE (server);
1199 soup_server_quit (server);
1201 if (priv->listen_sock) {
1202 soup_socket_disconnect (priv->listen_sock);
1203 g_object_unref (priv->listen_sock);
1204 priv->listen_sock = NULL;
1209 * soup_server_get_async_context:
1210 * @server: a #SoupServer
1212 * Gets @server's async_context. This does not add a ref to the
1213 * context, so you will need to ref it yourself if you want it to
1214 * outlive its server.
1216 * Return value: (transfer none): @server's #GMainContext, which may be %NULL
1219 soup_server_get_async_context (SoupServer *server)
1221 SoupServerPrivate *priv;
1223 g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
1224 priv = SOUP_SERVER_GET_PRIVATE (server);
1226 return priv->async_context;
1230 * SoupClientContext:
1232 * A #SoupClientContext provides additional information about the
1233 * client making a particular request. In particular, you can use
1234 * soup_client_context_get_auth_domain() and
1235 * soup_client_context_get_auth_user() to determine if HTTP
1236 * authentication was used successfully.
1238 * soup_client_context_get_address() and/or
1239 * soup_client_context_get_host() can be used to get information for
1240 * logging or debugging purposes. soup_client_context_get_socket() may
1241 * also be of use in some situations (eg, tracking when multiple
1242 * requests are made on the same connection).
1244 G_DEFINE_BOXED_TYPE (SoupClientContext, soup_client_context, soup_client_context_ref, soup_client_context_unref)
1247 * soup_client_context_get_socket:
1248 * @client: a #SoupClientContext
1250 * Retrieves the #SoupSocket that @client is associated with.
1252 * If you are using this method to observe when multiple requests are
1253 * made on the same persistent HTTP connection (eg, as the ntlm-test
1254 * test program does), you will need to pay attention to socket
1255 * destruction as well (either by using weak references, or by
1256 * connecting to the #SoupSocket::disconnected signal), so that you do
1257 * not get fooled when the allocator reuses the memory address of a
1258 * previously-destroyed socket to represent a new socket.
1260 * Return value: (transfer none): the #SoupSocket that @client is
1264 soup_client_context_get_socket (SoupClientContext *client)
1266 g_return_val_if_fail (client != NULL, NULL);
1268 return client->sock;
1272 * soup_client_context_get_address:
1273 * @client: a #SoupClientContext
1275 * Retrieves the #SoupAddress associated with the remote end
1278 * Return value: (transfer none): the #SoupAddress associated with the
1279 * remote end of a connection.
1282 soup_client_context_get_address (SoupClientContext *client)
1284 g_return_val_if_fail (client != NULL, NULL);
1286 return soup_socket_get_remote_address (client->sock);
1290 * soup_client_context_get_host:
1291 * @client: a #SoupClientContext
1293 * Retrieves the IP address associated with the remote end of a
1294 * connection. (If you want the actual hostname, you'll have to call
1295 * soup_client_context_get_address() and then call the appropriate
1296 * #SoupAddress method to resolve it.)
1298 * Return value: the IP address associated with the remote end of a
1302 soup_client_context_get_host (SoupClientContext *client)
1304 SoupAddress *address;
1306 address = soup_client_context_get_address (client);
1307 return soup_address_get_physical (address);
1311 * soup_client_context_get_auth_domain:
1312 * @client: a #SoupClientContext
1314 * Checks whether the request associated with @client has been
1315 * authenticated, and if so returns the #SoupAuthDomain that
1318 * Return value: (transfer none) (allow-none): a #SoupAuthDomain, or
1319 * %NULL if the request was not authenticated.
1322 soup_client_context_get_auth_domain (SoupClientContext *client)
1324 g_return_val_if_fail (client != NULL, NULL);
1326 return client->auth_domain;
1330 * soup_client_context_get_auth_user:
1331 * @client: a #SoupClientContext
1333 * Checks whether the request associated with @client has been
1334 * authenticated, and if so returns the username that the client
1337 * Return value: the authenticated-as user, or %NULL if the request
1338 * was not authenticated.
1341 soup_client_context_get_auth_user (SoupClientContext *client)
1343 g_return_val_if_fail (client != NULL, NULL);
1345 return client->auth_user;
1349 * SoupServerCallback:
1350 * @server: the #SoupServer
1351 * @msg: the message being processed
1352 * @path: the path component of @msg's Request-URI
1353 * @query: (element-type utf8 utf8) (allow-none): the parsed query
1354 * component of @msg's Request-URI
1355 * @client: additional contextual information about the client
1356 * @user_data: the data passed to @soup_server_add_handler
1358 * A callback used to handle requests to a #SoupServer. The callback
1359 * will be invoked after receiving the request body; @msg's
1360 * #SoupMessage:method, #SoupMessage:request_headers, and
1361 * #SoupMessage:request_body fields will be filled in.
1363 * @path and @query contain the likewise-named components of the
1364 * Request-URI, subject to certain assumptions. By default,
1365 * #SoupServer decodes all percent-encoding in the URI path, such that
1366 * "/foo%<!-- -->2Fbar" is treated the same as "/foo/bar". If your
1367 * server is serving resources in some non-POSIX-filesystem namespace,
1368 * you may want to distinguish those as two distinct paths. In that
1369 * case, you can set the %SOUP_SERVER_RAW_PATHS property when creating
1370 * the #SoupServer, and it will leave those characters undecoded. (You
1371 * may want to call soup_uri_normalize() to decode any percent-encoded
1372 * characters that you aren't handling specially.)
1374 * @query contains the query component of the Request-URI parsed
1375 * according to the rules for HTML form handling. Although this is the
1376 * only commonly-used query string format in HTTP, there is nothing
1377 * that actually requires that HTTP URIs use that format; if your
1378 * server needs to use some other format, you can just ignore @query,
1379 * and call soup_message_get_uri() and parse the URI's query field
1382 * After determining what to do with the request, the callback must at
1383 * a minimum call soup_message_set_status() (or
1384 * soup_message_set_status_full()) on @msg to set the response status
1385 * code. Additionally, it may set response headers and/or fill in the
1388 * If the callback cannot fully fill in the response before returning
1389 * (eg, if it needs to wait for information from a database, or
1390 * another network server), it should call soup_server_pause_message()
1391 * to tell #SoupServer to not send the response right away. When the
1392 * response is ready, call soup_server_unpause_message() to cause it
1395 * To send the response body a bit at a time using "chunked" encoding,
1396 * first call soup_message_headers_set_encoding() to set
1397 * %SOUP_ENCODING_CHUNKED on the #SoupMessage:response_headers. Then call
1398 * soup_message_body_append() (or soup_message_body_append_buffer())
1399 * to append each chunk as it becomes ready, and
1400 * soup_server_unpause_message() to make sure it's running. (The
1401 * server will automatically pause the message if it is using chunked
1402 * encoding but no more chunks are available.) When you are done, call
1403 * soup_message_body_complete() to indicate that no more chunks are
1408 * soup_server_add_handler:
1409 * @server: a #SoupServer
1410 * @path: (allow-none): the toplevel path for the handler
1411 * @callback: callback to invoke for requests under @path
1412 * @user_data: data for @callback
1413 * @destroy: destroy notifier to free @user_data
1415 * Adds a handler to @server for requests under @path. See the
1416 * documentation for #SoupServerCallback for information about
1417 * how callbacks should behave.
1419 * If @path is %NULL or "/", then this will be the default handler for
1420 * all requests that don't have a more specific handler. Note though
1421 * that if you want to handle requests to the special "*" URI, you
1422 * must explicitly register a handler for "*"; the default handler
1423 * will not be used for that case.
1426 soup_server_add_handler (SoupServer *server,
1428 SoupServerCallback callback,
1430 GDestroyNotify destroy)
1432 SoupServerPrivate *priv;
1433 SoupServerHandler *hand;
1435 g_return_if_fail (SOUP_IS_SERVER (server));
1436 g_return_if_fail (callback != NULL);
1437 priv = SOUP_SERVER_GET_PRIVATE (server);
1439 /* "" was never documented as meaning the same this as "/",
1440 * but it effectively was. We have to special case it now or
1441 * otherwise it would match "*" too.
1443 if (path && (!*path || !strcmp (path, "/")))
1446 hand = g_slice_new0 (SoupServerHandler);
1447 hand->path = g_strdup (path);
1448 hand->callback = callback;
1449 hand->destroy = destroy;
1450 hand->user_data = user_data;
1452 soup_server_remove_handler (server, path);
1454 soup_path_map_add (priv->handlers, path, hand);
1456 priv->default_handler = hand;
1460 unregister_handler (SoupServerHandler *handler)
1462 if (handler->destroy)
1463 handler->destroy (handler->user_data);
1467 * soup_server_remove_handler:
1468 * @server: a #SoupServer
1469 * @path: the toplevel path for the handler
1471 * Removes the handler registered at @path.
1474 soup_server_remove_handler (SoupServer *server, const char *path)
1476 SoupServerPrivate *priv;
1477 SoupServerHandler *hand;
1479 g_return_if_fail (SOUP_IS_SERVER (server));
1480 priv = SOUP_SERVER_GET_PRIVATE (server);
1482 if (!path || !*path || !strcmp (path, "/")) {
1483 if (priv->default_handler) {
1484 unregister_handler (priv->default_handler);
1485 free_handler (priv->default_handler);
1486 priv->default_handler = NULL;
1491 hand = soup_path_map_lookup (priv->handlers, path);
1492 if (hand && !strcmp (path, hand->path)) {
1493 unregister_handler (hand);
1494 soup_path_map_remove (priv->handlers, path);
1499 * soup_server_add_auth_domain:
1500 * @server: a #SoupServer
1501 * @auth_domain: a #SoupAuthDomain
1503 * Adds an authentication domain to @server. Each auth domain will
1504 * have the chance to require authentication for each request that
1505 * comes in; normally auth domains will require authentication for
1506 * requests on certain paths that they have been set up to watch, or
1507 * that meet other criteria set by the caller. If an auth domain
1508 * determines that a request requires authentication (and the request
1509 * doesn't contain authentication), @server will automatically reject
1510 * the request with an appropriate status (401 Unauthorized or 407
1511 * Proxy Authentication Required). If the request used the
1512 * "100-continue" Expectation, @server will reject it before the
1513 * request body is sent.
1516 soup_server_add_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain)
1518 SoupServerPrivate *priv;
1520 g_return_if_fail (SOUP_IS_SERVER (server));
1521 priv = SOUP_SERVER_GET_PRIVATE (server);
1523 priv->auth_domains = g_slist_append (priv->auth_domains, auth_domain);
1524 g_object_ref (auth_domain);
1528 * soup_server_remove_auth_domain:
1529 * @server: a #SoupServer
1530 * @auth_domain: a #SoupAuthDomain
1532 * Removes @auth_domain from @server.
1535 soup_server_remove_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain)
1537 SoupServerPrivate *priv;
1539 g_return_if_fail (SOUP_IS_SERVER (server));
1540 priv = SOUP_SERVER_GET_PRIVATE (server);
1542 priv->auth_domains = g_slist_remove (priv->auth_domains, auth_domain);
1543 g_object_unref (auth_domain);
1547 * soup_server_pause_message:
1548 * @server: a #SoupServer
1549 * @msg: a #SoupMessage associated with @server.
1551 * Pauses I/O on @msg. This can be used when you need to return from
1552 * the server handler without having the full response ready yet. Use
1553 * soup_server_unpause_message() to resume I/O.
1555 * This must only be called on #SoupMessages which were created by the
1556 * #SoupServer and are currently doing I/O, such as those passed into a
1557 * #SoupServerCallback or emitted in a #SoupServer::request-read signal.
1560 soup_server_pause_message (SoupServer *server,
1563 g_return_if_fail (SOUP_IS_SERVER (server));
1564 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1566 soup_message_io_pause (msg);
1570 * soup_server_unpause_message:
1571 * @server: a #SoupServer
1572 * @msg: a #SoupMessage associated with @server.
1574 * Resumes I/O on @msg. Use this to resume after calling
1575 * soup_server_pause_message(), or after adding a new chunk to a
1578 * I/O won't actually resume until you return to the main loop.
1580 * This must only be called on #SoupMessages which were created by the
1581 * #SoupServer and are currently doing I/O, such as those passed into a
1582 * #SoupServerCallback or emitted in a #SoupServer::request-read signal.
1585 soup_server_unpause_message (SoupServer *server,
1588 g_return_if_fail (SOUP_IS_SERVER (server));
1589 g_return_if_fail (SOUP_IS_MESSAGE (msg));
1591 soup_message_io_unpause (msg);