Building a simple Web server with arsd CGI framework
Frameworks for building web servers in the D programming language come with different conventions and design choices. I previously wrote about using the vibe.d web framework both in it's route-base style and declarative web interface style. However there's another alternative, the CGI style, which the arsd CGI web framework was designed with (kind of).
Ards CGI is just one module among a collection of modules under the arsd namespace.
The interesting thing about using arsd for me is it's simplicity and how lightweight it is. It's quite straightforward to get a web server up and running with very few lines of code. Moreover, arsd by default comes with zero system dependencies. It does not require you to install any system package to use unlike vibe.d. This advantage makes arsd easy to run in any environment especially when you do not have system access to install system dependencies (cloud functions, PaaS, etc).
Zero system dependencies!!
Now, I'm will be using the D package manager,
dub, to run the server app. Create a dub
project by running dub init arsd-cgi-demo
command from your command line where
arsd-cgi-demo
is your project's name. Make sure to add arsd-official:cgi
when prompted to add a dependency as follows:
dub init arsd-cgi-demo
Package recipe format (sdl/json) [json]:
Name [arsd-cgi-demo]:
Description [A minimal D application.]:
Author name [aberba]:
License [proprietary]:
Copyright string [Copyright © 2021, aberba]:
Add dependency (leave empty to skip) []: arsd-official:cgi
Adding dependency arsd-official:cgi ~>9.0.4
Add dependency (leave empty to skip) []:
Successfully created an empty project in '/home/aberba/workspace/d/arsd-cgi-demo'.
Package successfully created in arsd-cgi-demo
Dub comes bundled with the D compiler when installed.
So lets see an example server:
import arsd.cgi;
void handler(Cgi cgi)
{
cgi.setResponseContentType("text/html");
switch (cgi.pathInfo)
{
case "/":
cgi.write("Hello, World!");
break;
// other routes go here
default:
cgi.setResponseStatus("404 Not found");
cgi.write("Requested page not found.");
break;
}
}
void main()
{
RequestServer server;
server.listeningPort = 9000;
server.serve!handler;
}
That's all it takes. You first create a handler which takes a Cgi
parameter
with all the facilities to handle both receiving an http request and sending a
response.
cgi.pathInfo
is used to match the request route and response according. You
may also use cgi.requestMethod
to match the request method which may be one of
cgi.RequestMethod.GET
, cgi.RequestMethod.POST
, cgi.RequestMethod.PATCH
and
friends. The following code shows how you may do that in the handler
function:
void handler(Cgi cgi)
{
cgi.setResponseContentType("text/html");
switch (cgi.pathInfo)
{
case "/":
if (cgi.requestMethod == cgi.RequestMethod.GET)
{
cgi.write("Hello from GET");
}
else
{
// you may also send 404. Whatever you want, 🤷♀️
cgi.write("Hello, I'm also here.");
}
break;
// other routes go here
default:
cgi.setResponseStatus("404 Not found");
cgi.write("Requested page not found.");
break;
}
}
You may also notice that the cgi.setResponseStatus()
method for setting both a
response status code and text. The prefix, 404
, becomes the response code
whilst the text that follows, in this case Not found
, then becomes the status
text. This is a convention used in certain aspects of arsd CGI. I will dive into
those aspects in another post later.
Now since arsd CGI is written in D, a language with very powerful metaprogramming support, it is capable of abstracting things to minimize the lines of code needed to implement certain functionalities. Let's see the same example in an idiomatic D code:
import arsd.cgi;
void handler(Cgi cgi)
{
// the rest of the content goes here
}
mixin GenericMain!handler;
That's it!. No need to manually initialize a request server or register a port manually. Arsd takes care of generating the code needed to handle all of that for you. Pretty neat.
This is just a tease of what arsd CGI web framework can do. It also supports a declarative style for handling requests with a URL dispatcher. I will write about that later.
Now it's not all rainbow and sunshine with arsd CGI. It does not support all the features you might get out of the box with Vibe.d such a SSL cert integration (you may use NGINX as a proxy to handle SSL). This might be good thing or bad depending on what you are used to or your use case. As mentioned, arsd CGI is just one module in a whole collection. It's meant for you to pick and choose additional modules based on your needs including packages available in the D package repository.