Provides a uniform server-side API for CGI, FastCGI, SCGI, and HTTP web applications.

1 import arsd.cgi;
3 // Instead of writing your own main(), you should write a function
4 // that takes a Cgi param, and use mixin GenericMain
5 // for maximum compatibility with different web servers.
6 void hello(Cgi cgi) {
7 	cgi.setResponseContentType("text/plain");
9 	if("name" in cgi.get)
10 		cgi.write("Hello, " ~ cgi.get["name"]);
11 	else
12 		cgi.write("Hello, world!");
13 }
15 mixin GenericMain!hello;

Public Imports

public import std.string;
public import std.stdio;
public import std.conv;



class BufferedInputRange

This is NOT ACTUALLY an input range! It is too different. Historical mistake kinda.

class Cgi

The main interface with the web request

class EventSourceServer
class ListeningConnectionManager

To use this thing:

class WebSocket



string[][string] decodeVariables(string data, string separator = "&")

breaks down a url encoded string

string[string] decodeVariablesSingle(string data)

breaks down a url encoded string, but only returns the last value of any array

Cgi dummyCgi(Cgi.RequestMethod method = Cgi.RequestMethod.GET, string url = null, in ubyte[] data = null, void delegate(const(ubyte)[]) outputSink = null)

use this for testing or other isolated things

string encodeVariables(in string[string] data)

url encodes the whole string

string encodeVariables(in string[][string] data)

url encodes a whole string

string makeDataUrl(string mimeType, in void[] data)

Makes a data:// uri that can be used as links in most newer browsers (IE8+).

string rawurlencode(in char[] data)

Encodes all but the explicitly unreserved characters per rfc 3986 Alphanumeric and -_.~ are the only ones left unencoded name is borrowed from php


interface EventIoServer

You can customize your server by subclassing the appropriate server. Then, register your subclass at compile time with the registerEventIoServer template, or implement your own main function and call it yourself.

Mixin templates

mixin template CustomCgiMain(CustomCgi, alias fun, long maxContentLength = defaultMaxContentLength)

If you want to use a subclass of Cgi with generic main, use this mixin.

mixin template ForwardCgiConstructors()

If you are doing a custom cgi class, mixing this in can take care of the required constructors for you

mixin template GenericMain(alias fun, long maxContentLength = defaultMaxContentLength)

Use this instead of writing your own main


struct Uri

Represents a url that can be broken down or built up through properties

Detailed Description

Compile versions

-version=plain_cgi The default - a traditional, plain CGI executable will be generated. -version=fastcgi A FastCGI executable will be generated. -version=scgi A SCGI (SimpleCGI) executable will be generated. -version=embedded_httpd A HTTP server will be embedded in the generated executable. -version=embedded_httpd_threads The embedded HTTP server will use a single process with a thread pool. -version=embedded_httpd_processes The embedded HTTP server will use a prefork style process pool.

-version=cgi_with_websocket The CGI class has websocket server support.

-version=with_openssl # not currently used

-version=embedded_httpd_processes_accept_after_fork It will call accept() in each child process, after forking. This is currently the only option, though I am experimenting with other ideas.

-version=cgi_embedded_sessions The session server will be embedded in the cgi.d server process -version=cgi_session_server_process The session will be provided in a separate process, provided by cgi.d.

Compile and run

For CGI, dmd yourfile.d cgi.d then put the executable in your cgi-bin directory.

For FastCGI: dmd yourfile.d cgi.d -version=fastcgi and run it. spawn-fcgi helps on nginx. You can put the file in the directory for Apache. On IIS, run it with a port on the command line.

For SCGI: dmd yourfile.d cgi.d -version=scgi and run the executable, providing a port number on the command line.

For an embedded HTTP server, run dmd yourfile.d cgi.d -version=embedded_httpd and run the generated program. It listens on port 8085 by default. You can change this on the command line with the --port option when running your program.

You can also simulate a request by passing parameters on the command line, like:

./yourprogram GET / name=adr

And it will print the result to stdout.

CGI Setup tips

On Apache, you may do SetHandler cgi-script in your .htaccess file.

Integration tips

cgi.d works well with dom.d for generating html. You may also use web.d for other utilities and automatic api wrapping.

dom.d usage:

1 import arsd.cgi;
2 import arsd.dom;
4 void hello_dom(Cgi cgi) {
5 	auto document = new Document();
7 	static import std.file;
8 	// parse the file in strict mode, requiring it to be well-formed UTF-8 XHTML
9 	// (You'll appreciate this if you've ever had to deal with a missing </div>
10 	// or something in a php or erb template before that would randomly mess up
11 	// the output in your browser. Just check it and throw an exception early!)
12 	//
13 	// You could also hard-code a template or load one at compile time with an
14 	// import expression, but you might appreciate making it a regular file
15 	// because that means it can be more easily edited by the frontend team and
16 	// they can see their changes without needing to recompile the program.
17 	//
18 	// Note on CTFE: if you do choose to load a static file at compile time,
19 	// you *can* parse it in CTFE using enum, which will cause it to throw at
20 	// compile time, which is kinda cool too. Be careful in modifying that document,
21 	// though, as it will be a static instance. You might want to clone on on demand,
22 	// or perhaps modify it lazily as you print it out. (Try element.tree, it returns
23 	// a range of elements which you could send through std.algorithm functions. But
24 	// since my selector implementation doesn't work on that level yet, you'll find that
25 	// harder to use. Of course, you could make a static list of matching elements and
26 	// then use a simple e is e2 predicate... :) )
27 	document.parseUtf8("your_template.html"), true, true);
29 	// fill in data using DOM functions, so placing it is in the hands of HTML
30 	// and it will be properly encoded as text too.
31 	//
32 	// Plain html templates can't run server side logic, but I think that's a
33 	// good thing - it keeps them simple. You may choose to extend the html,
34 	// but I think it is best to try to stick to standard elements and fill them
35 	// in with requested data with IDs or class names. A further benefit of
36 	// this is the designer can also highlight data based on sources in the CSS.
37 	//
38 	// However, all of dom.d is available, so you can format your data however
39 	// you like. You can do partial templates with innerHTML too, or perhaps better,
40 	// injecting cloned nodes from a partial document.
41 	//
42 	// There's a lot of possibilities.
43 	document["#name"].innerText = cgi.request("name", "default name");
45 	// send the document to the browser. The second argument to `cgi.write`
46 	// indicates that this is all the data at once, enabling a few small
47 	// optimizations.
48 	cgi.write(document.toString(), true);
49 }

Concepts: Input: Cgi.get,, Cgi.request, Cgi.files, Cgi.cookies, Cgi.pathInfo, Cgi.requestMethod, and HTTP headers (Cgi.headers, Cgi.userAgent, Cgi.referrer, Cgi.accept, Cgi.authorization, Cgi.lastEventId)

Output: Cgi.write, Cgi.header, Cgi.setResponseStatus, Cgi.setResponseContentType, Cgi.gzipResponse

Cookies: Cgi.setCookie, Cgi.clearCookie, Cgi.cookie, Cgi.cookies

Caching: Cgi.setResponseExpires, Cgi.updateResponseExpires, Cgi.setCache

Redirections: Cgi.setResponseLocation

Other Information: Cgi.remoteAddress, Cgi.https, Cgi.port, Cgi.scriptName, Cgi.requestUri, Cgi.getCurrentCompleteUri, Cgi.onRequestBodyDataReceived

Overriding behavior: Cgi.handleIncomingDataChunk, Cgi.prepareForIncomingDataChunks, Cgi.cleanUpPostDataState

Installing: Apache, IIS, CGI, FastCGI, SCGI, embedded HTTPD (not recommended for production use)

Guide for PHP users

If you are coming from PHP, here's a quick guide to help you get started:

1 <?php
2 	$foo = $_POST["foo"];
3 	$bar = $_GET["bar"];
4 	$baz = $_COOKIE["baz"];
6 	$user_ip = $_SERVER["REMOTE_ADDR"];
7 	$host = $_SERVER["HTTP_HOST"];
8 	$path = $_SERVER["PATH_INFO"];
10 	setcookie("baz", "some value");
12 	echo "hello!";
13 ?>
1 import arsd.cgi;
2 void app(Cgi cgi) {
3 	string foo =["foo"];
4 	string bar = cgi.get["bar"];
5 	string baz = cgi.cookies["baz"];
7 	string user_ip = cgi.remoteAddress;
8 	string host =;
9 	string path = cgi.pathInfo;
11 	cgi.setCookie("baz", "some value");
13 	cgi.write("hello!");
14 }
16 mixin GenericMain!app

Array elements

In PHP, you can give a form element a name like "something[]", and then $_POST["something"] gives an array. In D, you can use whatever name you want, and access an array of values with the cgi.getArray["name"] and cgi.postArray["name"] members.


PHP has a lot of stuff in its standard library. cgi.d doesn't include most of these, but the rest of my arsd repository has much of it. For example, to access a MySQL database, download database.d and mysql.d from my github repo, and try this code (assuming, of course, your database is set up):

1 import arsd.cgi;
2 import arsd.mysql;
4 void app(Cgi cgi) {
5 	auto database = new MySql("localhost", "username", "password", "database_name");
6 	foreach(row; mysql.query("SELECT count(id) FROM people"))
7 		cgi.write(row[0] ~ " people in database");
8 }
10 mixin GenericMain!app;

Similar modules are available for PostgreSQL, Microsoft SQL Server, and SQLite databases, implementing the same basic interface.

See Also

You may also want to see arsd.dom, arsd.web, and arsd.html for more code for making web applications.

For working with json, try arsd.jsvar.

arsd.database, arsd.mysql, arsd.postgres, arsd.mssql, and arsd.sqlite can help in accessing databases.

If you are looking to access a web application via HTTP, try, arsd.curl, or arsd.http2.