Server¶
Server provide HTTP technologies integrations under a common interface.
Server implementations are dynamically loaded using gmodule-2.0/GLib.Module. It makes it possible to define its own implementation if necessary.
To load an implementation, use the Server.new factory, which can receive
GObject-style arguments as well.
var cgi_server = Server.new ("cgi");
if (cgi_server == null) {
assert_not_reached ();
}
cgi_server.set_application_callback ((req, res) => {
return res.expand_utf8 ("Hello world!");
});
Custom implementation¶
For more flexibility, the ServerModule class allow a more fine-grained
control for loading a server implementation. If non-null, the directory
property will be used to retrieve the implementation from the given path
instead of standard locations.
The computed path of the shared library is available from path property,
which can be used for debugging purposes.
The shared library name must conform to vsgi-<name> with the appropriate
prefix and extension. For instance, on GNU/Linux, the CGI module is
stored in ${prefix}/${libdir}/vsgi-0.3/servers/libvsgi-cgi.so.
var directory = "/usr/lib64/vsgi-0.3/servers";
var cgi_module = new ServerModule (directory, "cgi");
if (!cgi_module.load ()) {
error ("could not load 'cgi' from '%s'", cgi_module.path);
}
var server = Object.new (cgi_module.server_type);
Unloading a module is not necessary: once initially loaded, a use count is kept so that it can be loaded on need or unloaded if not used.
Warning
Since a ServerModule cannot be disposed (see gobject-2.0/GLib.TypeModule),
one must be careful of how its reference is being handled. For instance,
Server.new keeps track of requested implementations and persist them
forever.
Mixing direct usages of ServerModule and Server.@new (and the likes) is
not recommended and will result in undefined behaviours if an implementation is
loaded more than once.
Parameters¶
Each server implementation expose its own set of parameters via GObject properties which are passed using the provided static constructors:
var https_server = Server.new ("http", https: true);
More details on available parameters are presented in implementation-specific documents.
Listening¶
Once initialized, a server can be made ready to listen with listen and
listen_socket. Implementations typically support listening from an
arbitrary number of interfaces.
If the provided parameters are not supported, a gio-2.0/GLib.IOError.NOT_SUPPORTED will be raised.
The listen call is designed to make the server listen on a gio-2.0/GLib.SocketAddress
such as gio-2.0/GLib.InetSocketAddress and gio-2.0/GLib.UnixSocketAddress.
server.listen (new InetSocketAddress (new InetAddress.loopback (SocketFamily.IPV4), 3003));
It’s also possible to pass null such that the default interface for the
implementation will be used.
server.listen (); // default is 'null'
The listen_socket call make the server listen on an existing socket or file
descriptor if passed through GLib.Socket.from_fd.
server.listen_socket (new Socket.from_fd (0));
Serving¶
Once ready, either call Server.run or launch a glib-2.0/GLib.MainLoop
to start serving incoming requests:
using GLib;
using VSGI;
var server = Server.new ("http");
server.listen (new InetSocketAddress (new InetAddress (SocketFamily.IPV4), 3003));
new MainLoop ().run (); // or server.run ();
Forking¶
To achieve optimal performances on a multi-core architecture, VSGI support forking at the server level.
Warning
Keep in mind that the fork system call will actually copy the whole
process: no resources (e.g. lock, memory) can be shared unless
inter-process communication is used.
The Server.fork call is used for that purpose:
using GLib;
using VSGI;
var server = Server.new ("http");
server.listen (new InetSocketAddress (new InetAddress.loopback (SocketFamily.IPV4), 3003));
server.fork ();
new MainLoop ().run ();
It is recommended to fork only through that call since implementations such as CGI are not guaranteed to support it and will gently fallback on doing nothing.
Application¶
The VSGI.Application class provide a nice cushion around Server that
deals with pretty logging and CLI argument parsing. The Server.run function
is a shorthand to create and run an application.
using VSGI;
public int main (string[] args) {
var server = Server.new ("http");
return new Application (server).run (args);
}
CLI¶
The following options are made available:
| Option | Default | Description |
|---|---|---|
--forks |
none | number of forks to create |
--log-writer |
none | log writer to use |
--address |
none | listen on each addresses |
--port |
none | listen on each ports, ‘0’ for random |
--socket |
none | listen on each UNIX socket paths |
--any |
disabled | listen on any address instead of only from the loopback interface |
--ipv4-only |
disabled | listen only to IPv4 interfaces |
--ipv6-only |
disabled | listen only on IPv6 interfaces |
--file-descriptor |
none | listen on each file descriptors |
The --log-writer flag allow one to chose among various log writer
implementations:
standard-streamsjournalddefault
If no choice is made, no specific log writer is attached.
If none of --address, --port, --socket nor --file-descriptor
flags are provided, it will fallback on the default listening interface for the
implementation.
The --address flag uses gio-2.0/GLib.NetworkAddress.parse under
the hood, which properly interpret IPv4 and IPv6 addresses. It will also
resolve domains and parse ports. If no port is provided, a random one will be
used.
The default when --port is provided is to listen on both IPv4 and IPv6
interfaces, or just IPv4 if IPv6 is not supported.
Use the --help flag to obtain more information about available options.