Skip to content

Commit

Permalink
WIP: Provides options for the Soup.Server
Browse files Browse the repository at this point in the history
Exposes more features of the libsoup-2.4 HTTP server through CLI
arguments.

 - listening port
 - listen to all interfaces, only local or a file descriptor
 - listen to IPv4 or IPv6
 - server header
 - raw paths
 - https with ssl-cert-key and ssl-cert-file

Initializes the server with proper options.

Improves the listening message for the old libsoup-2.4 server API by
using information available in Soup.Server.interface.

Applies listen_options for the new server API so that HTTPS, IPv4 or
IPv6 can be targeted specifically.

The timeout option is applying only if it is specified, otherwise the
behiaviour is to keep the application alive. It is not necessary to rely
on a timeout value of '0' to disable it. The same fix is applied to the
FastCGI implementation.

Documents the newly available options using a table.
  • Loading branch information
arteymix committed Jun 23, 2015
1 parent 6e38efd commit 18ce073
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 29 deletions.
56 changes: 53 additions & 3 deletions docs/server/soup.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
libsoup built-in server
=======================
libsoup-2.4 built-in server
============================

libsoup provides a `built-in HTTP server`_ that you can use to test your
libsoup-2.4 provides a `built-in HTTP server`_ that you can use to test your
application or spawn workers in production.

.. _built-in HTTP server: http://valadoc.org/#!api=libsoup-2.4/Soup.Server
Expand All @@ -15,3 +15,53 @@ application or spawn workers in production.
new Server (app).run ({"app", "--port", "3003"});
Options
-------

The implementation provides most options provided by `Soup.Server`_ through
command-line options. The available options may vary and can be asserted with
the ``--help`` flag.

.. _Soup.Server: http://valadoc.org/#!api=libsoup-2.4/Soup.Server

+-----------------------+-----------+-----------------------------------------+
| Option | Default | Description |
+=======================+===========+=========================================+
| ``--port`` | 3003 | port the server is listening on |
+-----------------------+-----------+-----------------------------------------+
| ``--all`` | | listen on all interfaces |
+-----------------------+-----------+-----------------------------------------+
| ``--ipv4-only`` | | only listen to IPv4 interfaces |
+-----------------------+-----------+-----------------------------------------+
| ``--ipv6-only`` | | only listen on IPv6 interfaces |
+-----------------------+-----------+-----------------------------------------+
| ``--file-descriptor`` | 0 | listen to the provided file descriptor |
+-----------------------+-----------+-----------------------------------------+
| ``--https`` | | listen for https connections rather |
| | | than plain http |
+-----------------------+-----------+-----------------------------------------+
| ``--ssl-cert-file`` | | path to a file containing a PEM-encoded |
| | | certificate |
+-----------------------+-----------+-----------------------------------------+
| ``--ssl-key-file`` | | path to a file containing a PEM-encoded |
| | | private key |
+-----------------------+-----------+-----------------------------------------+
| ``--server-header`` | Valum/0.1 | value to use for the "Server" header on |
| | | Messages processed by this server. |
+-----------------------+-----------+-----------------------------------------+
| ``--raw-paths`` | | percent-encoding in the Request-URI |
| | | path will not be automatically decoded |
+-----------------------+-----------+-----------------------------------------+
| ``--timeout`` | | inactivity timeout in ms |
+-----------------------+-----------+-----------------------------------------+

Notes
~~~~~

- if ``--all`` is not supplied, the server will only listen to local
interfaces
- ``--all`` can be combined with ``--ipv4-only`` or ``--ipv4-only`` to listen
on all IPv4 or IPv6 interfaces
- if ``--https`` is specified, you must provide a SSL or TLS certificate along
with a private key
- not specifying ``--timeout`` keep the server alive forever
5 changes: 4 additions & 1 deletion examples/app/app.vala
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Valum;
using VSGI.Soup;

public void main (string[] args) {

var app = new Router ();
var lua = new Script.Lua ();
var mcd = new NoSQL.Mcached ();
Expand Down Expand Up @@ -308,4 +310,5 @@ app.status (Soup.Status.NOT_FOUND, (req, res) => {
template.stream (res);
});

new Server (app).run ({"app", "--port", "3003"});
new Server (app).run (args);
}
9 changes: 5 additions & 4 deletions src/vsgi/fastcgi.vala
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,9 @@ namespace VSGI.FastCGI {
}

var backlog = options.contains ("backlog") ? options.lookup_value ("backlog", VariantType.INT32).get_int32 () : 0;
var timeout = options.contains ("timeout") ? options.lookup_value ("timeout", VariantType.INT32).get_int32 () : 0;

this.set_inactivity_timeout (timeout);
if (options.contains ("timeout"))
this.set_inactivity_timeout (options.lookup_value ("timeout", VariantType.INT32).get_int32 ());
#endif

#if GIO_2_40
Expand Down Expand Up @@ -331,9 +331,10 @@ namespace VSGI.FastCGI {

source.attach (MainContext.default ());

// keep alive if there is no timeout
if (this.get_inactivity_timeout () > 0)
#if GIO_2_40
if (options.contains ("timeout"))
this.release ();
#endif

return 0;
}
Expand Down
107 changes: 86 additions & 21 deletions src/vsgi/soup.vala
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,26 @@ namespace VSGI.Soup {

#if GIO_2_40
const OptionEntry[] entries = {
{"port", 'p', 0, OptionArg.INT, null, "port used to serve the HTTP server", "3003"},
{"timeout", 't', 0, OptionArg.INT, null, "inactivity timeout in ms", "0"},
// port options
{"port", 'p', 0, OptionArg.INT, null, "port the server is listening on", "3003"},
{"all", 'a', 0, OptionArg.NONE, null, "listen on all interfaces '--port'"}, // only with '--port'
{"ipv4-only", '4', 0, OptionArg.NONE, null, "only listen to IPv4 interfaces"}, // only with '--port'
{"ipv6-only", '6', 0, OptionArg.NONE, null, "only listen on IPv6 interfaces"}, // only with '--port'

// fd options
{"file-descriptor", 'f', 0, OptionArg.INT, null, "listen to the provided file descriptor", "0"},

// https options
{"https", 0, 0, OptionArg.NONE, null, "listen for https connections rather than plain http"},
{"ssl-cert-file", 0, 0, OptionArg.FILENAME, null, "path to a file containing a PEM-encoded certificate"},
{"ssl-key-file", 0, 0, OptionArg.FILENAME, null, "path to a file containing a PEM-encoded private key"},

// headers options
{"server-header", 'h', 0, OptionArg.STRING, null, "value to use for the 'Server' header on Messages processed by this server", "Valum/0.1"},
{"raw-paths", 0, 0, OptionArg.NONE, null, "percent-encoding in the Request-URI path will not be automatically decoded"},

// various options
{"timeout", 't', 0, OptionArg.INT, null, "inactivity timeout in ms"},
{null}
};
this.add_main_option_entries (entries);
Expand All @@ -128,27 +146,61 @@ namespace VSGI.Soup {
#if GIO_2_40
var options = command_line.get_options_dict ();

if (options.contains ("port") && options.contains ("socket"))
error ("either port or socket can be specified, not both");
if (options.contains ("port") && options.contains ("file-descriptor"))
error ("'--port' and '--file-descriptor' cannot be specified together");

var port = options.contains ("port") ? options.lookup_value ("port", VariantType.INT32).get_int32 () : 3003;
var timeout = options.contains ("timeout") ? options.lookup_value ("timeout", VariantType.INT32).get_int32 () : 0;
#else
var port = 3003;
var timeout = 0;
#endif
var port = options.contains ("port") ?
options.lookup_value ("port", VariantType.INT32).get_int32 () :
3003;

this.set_inactivity_timeout (timeout);
var file_descriptor = options.contains ("file-descriptor") ?
options.lookup_value ("file-descriptor", VariantType.INT32).get_int32 () :
0;

#if SOUP_2_48
this.server = new global::Soup.Server (global::Soup.SERVER_SERVER_HEADER, "Valum");
var server_header = options.contains ("server-header") ?
options.lookup_value ("server-header", VariantType.STRING).get_string () :
"Valum/0.1";

ServerListenOptions listen_options = 0;

if (options.contains ("https"))
listen_options |= ServerListenOptions.HTTPS;

if (options.contains ("ipv4-only"))
listen_options |= ServerListenOptions.IPV4_ONLY;

if (options.contains ("ipv6-only"))
listen_options |= ServerListenOptions.IPV6_ONLY;

if (options.contains ("timeout"))
this.set_inactivity_timeout (options.lookup_value ("timeout", VariantType.INT32).get_int32 ());
#else
this.server = new global::Soup.Server (global::Soup.SERVER_SERVER_HEADER, "Valum",
global::Soup.SERVER_PORT, port);
var port = 3003;
var file_descriptor = 0;
var server_header = "Valum/0.1";
#endif

this.hold ();

this.server = new global::Soup.Server (
#if !SOUP_2_48
global::Soup.SERVER_PORT, port,
#endif
#if SOUP_2_40
global::Soup.SERVER_RAW_PATHS, options.contains ("raw-paths"),
#endif
global::Soup.SERVER_SERVER_HEADER, server_header);

#if GIO_2_40
if (options.contains ("https")) {
assert (options.contains ("ssl-cert-file") && options.contains ("ssl-key-file"));
this.server.set_ssl_cert_file (options.lookup_value ("ssl-cert-file",
VariantType.BYTESTRING).get_bytestring (),
options.lookup_value ("ssl-key-file",
VariantType.BYTESTRING).get_bytestring ());
}
#endif

// register a catch-all handler
this.server.add_handler (null, (server, msg, path, query, client) => {
this.hold ();
Expand All @@ -164,21 +216,34 @@ namespace VSGI.Soup {
});

#if SOUP_2_48
this.server.listen_all (port, 0);
#if GIO_2_40
if (options.contains ("file-descriptor")) {
this.server.listen_fd (file_descriptor, listen_options);
} else if (options.contains ("all")) {
this.server.listen_all (port, listen_options);
} else
#endif
{
this.server.listen_local (port, listen_options);
}

foreach (var uri in this.server.get_uris ()) {
message ("listening on %s://%s:%u", uri.scheme, uri.host, uri.port);
}
#else
this.server.run_async ();
message ("listening on http://0.0.0.0:%u", this.server.port);
this.server.run ();

message ("listening on %s://%s:%u", this.server.@interface.protocol,
this.server.@interface.name,
this.server.@interface.port);
#endif

// keep alive if timeout is 0
if (this.get_inactivity_timeout () > 0)
#if GIO_2_40
if (options.contains ("timeout"))
this.release ();
#endif

return 0; // continue processing
return 0;
}
}
}

0 comments on commit 18ce073

Please sign in to comment.