arsd.cgi

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

1 import arsd.cgi;
2 
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");
8 
9 	if("name" in cgi.get)
10 		cgi.write("Hello, " ~ cgi.get["name"]);
11 	else
12 		cgi.write("Hello, world!");
13 }
14 
15 mixin GenericMain!hello;

Members

Classes

BufferedInputRange
class BufferedInputRange
Cgi
class Cgi

The main interface with the web request

ListeningConnectionManager
class ListeningConnectionManager

To use this thing:

WebSocket
class WebSocket

WEBSOCKET SUPPORT:

Functions

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

breaks down a url encoded string

decodeVariablesSingle
string[string] decodeVariablesSingle(string data)

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

dummyCgi
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

encodeVariables
string encodeVariables(in string[string] data)

url encodes the whole string

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

url encodes a whole string

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

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

rawurlencode
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

Mixin templates

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

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

ForwardCgiConstructors
mixin template ForwardCgiConstructors()

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

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

Use this instead of writing your own main

Structs

Uri
struct Uri

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

Detailed Description

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;
3 
4 void hello_dom(Cgi cgi) {
5 	auto document = new Document();
6 
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(std.file.read("your_template.html"), true, true);
28 
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");
44 
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.post, 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:

$_GET["var"] == cgi.get["var"]
$_POST["var"] == cgi.post["var"]
$_COOKIE["var"] == cgi.cookies["var"]

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.

echo("hello"); == cgi.write("hello");

$_SERVER["REMOTE_ADDR"] == cgi.remoteAddress
$_SERVER["HTTP_HOST"] == cgi.host

See Also

You may also want to see dom.d, web.d, and html.d for more code for making web applications. database.d, mysql.d, postgres.d, and sqlite.d can help in accessing databases.

If you are looking to access a web application via HTTP, try curl.d.

Meta

Suggestion Box / Bug Report