> But I'm curious how you do web programming with D. Do you use CGI? Yes, for most my apps (some have a homegrown HTTP server they use instead, if persistence is necessary).
The module is here: http://arsdnet.net/dcode/cgi.d That same module works with standard CGI and with the embedded http server, just with different constructors. The default one reads CGI variables, and the alternative takes http header and body fed to it from the network class. > How do you do all the HTTP stuff (parsing form data, etc.) You can see in the code that it's pretty straightforward. With the CGI standard, the webserver passes you data through stdin and environment variables. For GET and COOKIE variables, you check the relevant environment variable (QUERY_STRING and HTTP_COOKIE, respectively), then url decode them and use the resulting string arrays. For POST, you first check the CONTENT_TYPE and CONTENT_LENGTH environment variables, then pull in data from stdin (same as any simple program, except you know the length you want too). The content type can be one of many options. Regular forms are x-www-url-encoded (or something like that) and you decode them identically to the query string. My class puts them into an associative array, similar to PHP: immutable string[string] get; immutable string[string] post; immutable string[string] cookies; Names can also be repeated in a web form. PHP does this with a naming convention: if you put [] after the name in the form, it loads up a dynamic array in the field. So name="mything[]", repeated, becomes $_POST["mything"], which is an Array. I did it differently - there's simply an alternative variable to access them: immutable string[][string] getArray; // ditto for post The names are preserved from the form exactly. This is the lowest level access: ?key=value is there as getArray["key"][0] == "value". I don't try to follow PHP's convention. (As you can see, getArray["key"][0] is always usable. But since I find this relatively rare, I also offer plain get["key"] as a shortcut to it.) Where PHP uses globals for this, I used class members. So you'd actually write: Cgi cgi = new Cgi(); cgi.get["key"]; And so on. That handles strings, but there's other content types too. The most common alternative is used for file uploads. File upload forms have a content type of multipart/form-data, which is a MIME style encoding, similar to email attachments. The content type gives a boundary string. You search stdin for the boundary, then read some part headers, and finally the data, ending with the boundary string again. This continues until you hit "--" ~ boundary. Field names are no longer given by key=value like in urlencoding. It's passed as a field header, after the boundary, before the content. The original filename for file uploads is passed the same way. The CGI class takes care of all this for you, loading up the same associative arrays you get with a normal form. If there are files uploaded though, you access them through: cgi.files["name_from_form"] Which returns an UploadedFile struct. It includes the metadata passed along and the file's contents as a byte array. (You can expect this wouldn't work for very large files. That's probably why PHP uses a temporary file, but I find that such a hassle that I wanted to avoid it. My class currently simply rejects too big files, since I've not needed to solve that problem yet! All my apps only accept small files to upload anyway, little spreadsheet attachments, photos, etc., all of which easily fit in memory.) Anyway, saving file is as simple as: std.file.write("some name", cgi.files["myfile"].content); You can also use the member strings filename and contentType of that UploadedFile struct to get more info. Writing response data back to the user's browser is a simple case of writing things to stdout. First comes headers, then data. I abstracted this with the class too: cgi.write(); // write's response data, like php's echo For headers, there's some specific functions to do it, or a generic header() method that works just like PHP's. cgi.setResponseLocation("/"); // does a 302 redirect cgi.setResponseContentType("image/png"); // tell the browser a png is coming cgi.write("hello!"); // write data See the cgi.d file for details and more. The reason I provide these instead of just letting the user code use writefln() or whatever directly is: a) isolate them from handling the headers. It isn't hard to do, but it is easy to make mistakes and it's a bit tedious. The class takes care of it for you every time. b) writefln() won't work in the embedded server environment. cgi.write, on the other hand, will. (It implements this via a delegate passed to the constructor. It passes your data to the delegate, which is responsible for forwarding it to the network) Embedded server headers are slightly different than CGI headers too. The helper functions keep these changes from affecting user code. Switching from CGI to embedded server, if you use the class, it often as simple as changing the constructor call, keeping the rest of the code unchanged. In theory, FastCGI or other protocols could be added through additional constructors too. I haven't done this myself though because plain old CGI is both well supported and quite fast, despite it's reputation. (I think CGI got the blame for Perl's slowness more than its own weaknesses. Yes, it's startup and some parts of the output is slower than something like mod_php, but the program itself still runs as fast as it runs. For D, that means it blows PHP's speed out of the water. Startup time tends to have a disproportionate impact on benchmarks, because those benchmarks don't actually do anything interesting! Once your program does something useful, the time it spends doing real work will quickly outgrow the startup time, so that slight initial delay becomes irrelevant in the overall result.) > and templating? I have two methods that I use together: a TemplatedDocument class, and a plain old (well, extended) DOM style Document class. TemplatedDocument extends Document, so everything about the latter applies to the former. You start with a well-formed HTML file. This might be build out of the text of several files. e.g: auto document = new TemplatedDocument( std.file.readText("header.html" ) ~ std.file.readText("mypage.html" ) ~ std.file.readText("footer.html" )); Now you have a DOM object that you can grow or modify with your content. Building a tree with the standard DOM is tedious, but I have some extensions to help with that. document.getElementById("some-holder").innerText = my_name; The innerText method, borrowed from Internet Explorer, is one of the most useful. You can get or set plain text, with the object taking care of encoding. Alternatively, the HTML file might have a placeholder: <h1>{$title}</h1> And you fill those into the document via a simple AA: document.vars["title"] = "My cool site & stuff"; Document vars are automatically encoded for HTML before being output. The only way to put raw html in the output is to use the innerHTML DOM method and friends or to use the innerRawSource extension. (HTML may try to check for well-formedness. innerRawSource just takes your word for it and doesn't attempt to build an object tree.) This is meant to ensure the easy way is the correct way. Explicit encoding or decoding is rarely necessary. My template class offers no way to loop. All it does is that placeholder variable thing. To loop, do it yourself. One of my pages defines a custom html tag: <repeat times="10"> hello! </repeat> Then you can implement it in the code like so: foreach(e; document.getElementsByTagName("repeat")) { string html; foreach(i; 0 .. to!int(e.times)) // attributes are accessible like in javascript html ~= e.innerHTML; // get the inner contents e.outerHTML = html; // replace this tag with those contents } (For fancier modifications, there's also a getElementsBySelector, letting you do CSS style loops.) However, I'm more likely to just build those portions with the DOM, with the template saying where it goes: <div id="messages-holder"></div> auto holder = document.getElementById("messages-holder"); foreach(message; messages) { holder.addChild("p", message); // a shortcut method to create a child, set its text, and append it all in one } Some people believe this is no better than putting html output in your code as strings; it basically does the same thing. But I don't agree this is a big problem: a) You can still keep it separate with functions. See nntp.d for an example of this in practice. getMessage() returns a Post object. getMessagePage() takes a Post object and returns a Document. (Note this is handled automatically by the FancyMain mixin, defined in web.d, used in nntp.d. I've been mostly describing the lower level classes in this post: cgi.d and dom.d. web.d builds upon them to automate a lot of common tasks and to try to force more MVC separation. For an example of why this is cool, check this out: http://arsdnet.net/d-web-site/nntp/get-message?newsgroup=digitalmars.D&messageId=<ii4993%241l5b%241%40digitalmars.com>&format=json See the "&format=json" at the end? It outputs that message object as json instead of the HTML page! There's no code in nntp.d to do this - it's handled automatically by web.d. There's a variety of formats available. Try table, xml, string, and html too. They don't all work as well here because Post is a class rather than a struct (web.d currently works much better with simple structs than with fancy structs or classes), but in the future or in other projects, they would work too.) Back to templates in general, I also think HTML itself really isn't layout nor style. Layout is done by the skeleton html files, not the in code dom, and style is done with CSS. For example, nntp.d doesn't do inline styles. It just describes the data with tags and attributes, letting CSS finish the job of colors and other such details. My large work project currently has 6 skins for it, all written independently of the code. None of the D had to be changed, despite me using the dom to build out content loops. The dom extensions also save huge amounts of time. Take this: auto form = cast(Form) document.getElementById("my-form"); foreach(k, v; cgi.post) form.setValue(k, v); That takes all the POST variables and sets them in the given form. Whether the form is built out of inputs, radio boxes, selects, textareas - it doesn't matter. The Form class abstracts it all away to a uniform interface. (If it doesn't find a matching field in the given HTML, it automatically appends an <input type="hidden"> with the given values.) Not having to write: <input type="text" name="something" value="<?= $something ?>" /> Oops, I didn't htmlEntitesEncode that something, XSS time! <select name="Something"> <option value="a" <?php if($a == "a") echo "selected=\"selected\"";?>>My Option</option> <option value="b" <?php if($a == "b") echo "selected=\"selected\"";?>>My Option</option> </select> Sucks ass compared to form.setValue("Something", "a"); That alone infinitely outweighs any counter argument I've heard to my use of of a customized DOM. I've been typing this for a long time, I'm going to break up comments on the rest of your post into a separate message.