VSGI¶
VSGI is a middleware that interfaces different Web server technologies under a common and simple set of abstractions.
As of Valum 0.4, VSGI is distributed in its own repository and can be used as-is. Efforts are put toward making it portable (i.e. work on Windows) and more efficient.
VSGI produces process-based applications that are able to communicate with various HTTP servers using standardized protocols.
Handler¶
The entry point of any VSGI application implement the vsgi-0.3/VSGI.Handler abstract class. It provides a function of two arguments: a Request and a Response that return a boolean indicating if the request has been or will be processed. It may also raise an error.
using VSGI;
public class App : Handler {
public override bool handle (Request req, Response res) throws Error {
// process the request and produce the response...
return true;
}
}
Server.new ("http", handler: new App ()).run ();
If a handler indicate that the request has not been processed, it’s up to the server implementation to decide what will happen.
Asynchronous handling¶
New in version 0.4.
To go asynchronous, one can override the vsgi-0.3/VSGI.Handler.handle_async symbol instead.
using VSGI;
public class App : Handler {
public override async bool handle_async (Request req, Response res) throws Error {
// process the request and produce the response...
return true;
}
}
Server.new ("http", handler: new App ()).run ();
From now on, examples will consist of vsgi-0.3/VSGI.Handler.handle content to remain more concise.
Error handling¶
New in version 0.3.
At any moment, an error can be raised and handled by the server implementation which will in turn teardown the connection appropriately.
throw new IOError.FAILED ("some I/O failed");
Dynamic loading¶
New in version 0.3.
It could be handy to dynamically load handlers the same way Server are.
Fortunately, this can be performed with the HandlerModule
by providing
a directory and name for the shared library containing a dynamically loadable
application.
var module = var new HandlerModule ("<directory>", "<name>");
Server.new ("http", handler: Object.new (module.handler_type)).run ();
The only required definition is a handler_init
symbol that return the type
of some Handler
. In this case, the library should be located in <directory>/lib<name>.so
,
although the actual name is system-dependant.
[ModuleInit]
public Type handler_init (TypeModule type_module) {
return typeof (App);
}
public class App : Handler {
public bool handle (Request req, Response res) {
return res.expand_utf8 ("Hello world!");
}
}
Loader¶
New in version 0.4.
VSGI provide the vsgi-loader
utility designed to serve handlers written as
gmodule-2.0/GLib.Module from any supported implementation, no
recompilation needed.
Furthermore, it also provide a live-reloader based on gio-2.0/GLib.FileMonitor to remove the necessity of restarting the server if the application code changes.
Usage¶
The vsgi-loader
program can be used as follow:
vsgi-loader [--directory=<directory>] [--server=<server>] [--live-reload] <module_name> -- <server_arguments>
- the
directory
where the shared library is located or default system path - the
server
implementation which is eitherhttp
,fastcgi
orscgi
and defaults tohttp
- if
--live-reload
is set, the server will automatically reload the shared library on change - the name of the library without the
lib
prefix and.so
extension - arguments for the server implementation specified by the
--server
flag and delimited by--
Warning
Arguments for the server implementation must be separated by a --
indicator, otherwise they will be interpreted by vsgi-loader
.
vsgi-loader --directory=build/examples/loader loader -- --port=3005
Additional arguments are described in vsgi-loader --help
.
vsgi-loader --help
For details about server-specific options, the --help
flag can be passed
beyond.
vsgi-loader --server=fastcgi app -- --help
Initialization¶
To perform initialization, one can implement the gio-2.0/GLib.Initable interface, it will automatically be called by the loader.
[ModuleInit]
public Type handler_init (TypeModule type_module) {
return typeof (App);
}
public class App : Handler, Initable {
public Gda.Connection database { get; construct; }
public bool init (Cancellable? cancellable = null) throws Error {
database.open ();
}
public bool handle (Request req, Response res) {
return res.expand_utf8 ("Hello world!");
}
}