Creating a web API with web.d

My web.d file is an add-on module for cgi.d that utilizes D's reflection and code generation capabilities to automate tasks such as URL routing and JSON and HTML generation from your code.

Getting ready

The web.d file has several dependencies that can be found in my Github repository. You'll need to download each of the files and compile them all together. Download cgi.d, web.d, sha.d, dom.d, and characterencodings.d to your project's directory.

How to do it…

Let's execute the following steps to create a web API:

  1. Import arsd.web.
  2. Create a class that inherits from ApiProvider.
  3. Write the export methods, which implement various functions that you want to expose.
  4. Mix in a main function from the library with mixin FancyMain!Your_Class_name;.
  5. Compile the program and all dependencies together using any version modifiers you want from cgi.d or web.d. We can compile with the following command to use the embedded HTTP server and disable the automatic creation of session files:
    dmd yourfile.d cgi.d web.d sha.d dom.d characterencodings.d -version=no_automatic_session -version=embedded_httpd
    
  6. Access the functions from a web browser, JavaScript, or any other programming language through HTTP.

The code is as follows:

import arsd.web;
class Test : ApiProvider {
  export int add(int a, int b) { return a+b; }
  export string sayHello(string name) {
    return "Hello, " ~ name;
  }
}
mixin FancyMain!Test;

If you go to http://localhost:8085/add or http://localhost:8085/say-hello, you will see the automatic form and can fill it out to see the result of the corresponding function. You can see the machine-consumable result by going to http://localhost:8085/add?a=1&b=2&envelopeFormat=json&format=json.

How it works…

The implementation of web.d was one of my earliest explorations of compile-time reflection and code generation, and as such, its code is not very pretty to look at, but the results are remarkable.

Using __traits(derivedMembers), web.d inspects each method in your ApiProvider subclass, looking for other compatible types and functions marked with the export protection level (checking with __traits(getProtection)).

It recursively scans compatible types, for example, other ApiProvider instances, to prepare a tree of URL-mapped functions and objects. The export methods anywhere in the tree are made available through the Web by automatically generating a wrapper function for them.

The wrapper function translates an associative array of parameters from the web request into the typed arguments expected by the method. Then, the method is run and the return value is automatically formatted based on an optional pair of URL parameters: format and envelopeFormat.

The format parameter controls the format of the data (for example, html, json, or table) and envelopeFormat controls the format of the surrounding metadata (possible options include html, which wraps the content in an HTML document for presentation in the browser, and json, which is meant for machine consumption). The wrapper function also catches any exceptions thrown by the method and also forwards them to the API client or web browser.

The formatting implementation uses compile-time reflection paired with conditional compilation to automatically handle most types. If the necessary code to support a format does not compile, attempting to use that format will throw an exception at runtime.

The web.d module also uses the information it gathers from compile-time reflection to automatically generate HTML forms that can be used as a prototype UI for the functions.

There's more…

The web.d module also includes an HTML template engine that extends dom.d (which we'll use in the next recipe), an ApiObject type to create RESTful resources, and web session support that can be file- or cookie-backed. Moreover, web.d works well with html.d. Also, my Github repository provides methods for HTML sanitization (done via the DOM parser and a whitelist of allowed tags), CSS denesting and macro expansion similar to the SCSS project, and more. However, these modules aren't very well documented at this time, however, so if you want to experiment with them, look at the source code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.190.211