Chapter 10. Taking D Online

Looking back at the version of MovieMan we developed over the course of the first seven chapters of this book, its console-based interface is far from user-friendly and its array-based database doesn't have much in the way of scalability. It serves its purpose as a playground for D language features, but if anyone wanted to seriously consider a more appealing application, they would want to provide a user-friendly GUI of one form or another. To support multiple users (or extremely large DVD collections), an actual database should replace the simple arrays in db.d. A web-based version of MovieMan would fit the bill nicely. That's quite convenient for us, given that this chapter is about web development with D.

This chapter presents a brief introduction to vibe.d, an asynchronous I/O framework often used to develop web applications in D. It begins with a look at what vibe.d offers, then demonstrates the basics by showing one way to implement MovieMan as a web app. The end result is much nicer than the primitive command line app presented in previous chapters and serves as a better foundation for expansion and exploration, ideas for which are presented at the end of the chapter. The flow of the chapter looks like this:

  • Introduction: an overview of key vibe.d packages, the anatomy of a vibe.d web app, and a look at potential database APIs to use with MovieManWeb
  • MovieManWeb: a step-by-step walkthrough showing one possible implementation of MovieMan as a vibe.d web app, and ideas for how to expand the project

The software

Although the web app framework provided by vibe.d is a major selling point of the project, it's not the only reason vibe.d exists. In this section, we'll explore some of the key features vibe.d offers for different types of client-server applications. We'll close with a quick look at d2sqlite3, the database library we'll use in the MovieManWeb example project.

vibe.d

The vibe.d project, located at http://vibed.org/, is billed as "Asynchronous I/O that doesn't get in your way". Strip away the web app and REST layers, the HTTP and database packages, plus all the accompanying utilities, and you're left with a fast, event-based, asynchronous I/O framework suitable for just about any sort of client-server application you can imagine. Here, we'll take a quick look at some of the key vibe.d packages to see how things break down, followed by a brief overview of what a vibe.d web app looks like.

Package overview

vibe.d contains several packages that provide a variety of functionality for different layers of web development. From low-level socket handling to the high-level web framework, the packages can be used as needed to meet the needs of a server application. Following is a brief introduction to some of the packages:

  • The vibe.core package is the heart of vibe.d and the foundation upon which the rest of the framework is built. Here live the modules for fiber-aware concurrency, asynchronous event handling, file handling, TCP and UDP sockets, and logging. Any project that requires an asynchronous I/O framework can make use of this package in isolation.
  • vibe.http provides HTTP 1.1/1.0 client and server implementations, an HTTP file server, web sockets, a URL router, session management, a form data handler, an HTTP-based logger, and more. Sitting on top of vibe.core, vibe.http is somewhat analogous to the Java Servlet API. It's a barebones web-app framework with a few bells and whistles. At this level, the user must explicitly verify HTTP POST and GET parameters, set the content type, throw exceptions on bad requests, and generally do all of the work that is handled internally by the higher-level vibe.web package.
  • vibe.web is built atop vibe.http to allow for convenient declarative web and REST interfaces. It also has modules for validating HTTP parameters and handling internationalization. The MovieManWeb application makes uses of the declarative web interface to simplify the implementation.
  • vibe.mail provides a single module that contains an SMTP client implementation. vibe.db contains interfaces for the Mongo and Redis database APIs. Most of the remaining packages are utilities used internally by the other framework packages. There are packages for cryptography, data serialization, data streams, text parsing, data structures, and more.

As a demonstration of a vibe.d based server that expands on what vibe.d provides, take a look at vibenews at https://github.com/rejectedsoftware/vibenews. The project includes a web forum, but also implements an NNTP server using the vibe.core and vibe.stream packages.

The anatomy of a vibe.d web app

Getting started with vibe.d is extremely easy with DUB. In fact, DUB began life as a tool for generating and building vibe.d projects and distributing vibe.d extensions. Only later did it morph into a more generic build tool and package manager. Its roots as a vibe.d specific tool live on in the init command that we first saw way back in Chapter 1, How to Get a D in Programming. It takes an optional argument, -t, to specify the type of project to create. There are three options:

  • minimal: This is the default when -t is not specified. It creates a standard D application with a main function.
  • vibe.d: This creates a vibe.d project that implements a minimal HTTP server.
  • deimos: This generates a skeleton for a Deimos-like static binding to a C library.

To get a look at a simple vibe.d app, open up a command prompt to any directory and execute the following command:

dub init MyWebApp -t vibe.d

This creates a MyWebApp directory with the layout shown in the following screenshot:

The anatomy of a vibe.d web app

The first file in the list, .gitignore, is a convenience for those working with the git source control program. Quite a number of D projects live on GitHub and private git servers. .gitignore is a text file that contains a list of file patterns git should not consider when evaluating local changes. dub.sdl is the DUB project configuration we're already familiar with. For this vibe.d based project, it looks like this:

name "mywebapp"
description "A simple vibe.d server application."
copyright "Copyright © 2015, Mike Parker"
authors "Mike Parker"
dependency "vibe-d" version="~>0.7.23"
versions "VibeDefaultMain"

The only thing here that should warrant explanation at this point is the VibeDefaultMain version. When this version is specified, vibe.d apps need not implement a main function; the implementation in the vibe.appmain module will be used instead. This is a simple implementation that does some logging, runs the event loop, and catches all exceptions. It can be overridden by specifying VibeCustomMain as a version in the configuration file.

Note

As I write, an alpha version of vibe.d 0.7.26 is available for testing. In previous releases, if neither VibeDefaultMain nor VibeCustomMain were specified, the former would be the default. With the latest alpha, which will likely be released by the time this book is complete, the default is the latter. Regardless, DUB explicitly configures VibeDefaultMain in the generated dub.sdl.

The public folder is where publicly accessible files, such as static HTML pages and style sheets, should be saved. The source folder is for the source code and, just as with a normal DUB app, the tool looks for source/app.d by default. Finally, the views folder is for Diet templates, an HTML template engine based on Jade (much of the documentation at http://jade-lang.com/ serves for Diet templates as well). We'll dig a bit into the details when we implement MovieManWeb.

Peek into the source directory and you'll find that DUB has generated a default app.d. It does everything necessary to set up a minimal HTTP server that accepts connections and perpetually serves a plain text document that says, "Hello, World!". The unmodified output of that file follows:

import vibe.d;

shared static this()
{
  auto settings = new HTTPServerSettings;
  settings.port = 8080;
  settings.bindAddresses = ["::1", "127.0.0.1"];
  listenHTTP(settings, &hello);

  logInfo("Please open http://127.0.0.1:8080/ in your browser.");
}

void hello(HTTPServerRequest req, HTTPServerResponse res)
{
  res.writeBody("Hello, World!");
}

First off, notice the import of vibe.d at the top of the file. Although any D programmer should know that this indicates a file with the path vibe/d.d, it is all too easy for the human brain to subconsciously interpret it as a file named vibe.d (full disclosure: it happens to me every time I see it). Since the module does nothing more than publicly import vibe.vibe, then anyone bothered by vibe.d can directly import vibe.vibe instead.

The next thing to point out is that there is no main function in sight. We already know that vibe.d has its own implementation of main. When using the default main, all of the initialization the app requires should happen in a module constructor. As you can see, getting a minimal HTTP server up and running with vibe.d requires very little initialization. This generated implementation uses the low-level API from vibe.http. First, the connection settings for the server are set up in an HTTPServerSettings instance, then listenHTTP is called to start listening for active connections. The function is given a pointer to the hello function, which accepts HTTPServerRequest and HTTPServerResponse objects. Since this particular function isn't interested in any input from the request, it only concerns itself with the response by printing a plain text message, which is sent back to the browser.

There are more complex examples of how to use the low-level API in the project's source repository at https://github.com/rejectedsoftware/vibe.d, as well as in the documentation at the project home page.

The database library

There are a number of database options available for any vibe.d app. As shown previously, bindings for MongoDB and Redis ship with the project in the vibe.db package. More packages can be found in the DUB registry for other database distributions. Some of those libraries can automatically make use of the vibe.d networking layer when it is available. Some of them are native D APIs with no external dependencies, while others are bindings to C libraries.

A handful of database options were considered for the MovieManWeb project we'll develop in this chapter. The primary goal was to select a database that requires minimal effort to install and set up. The focus of this chapter is on programming a vibe.d app, not on setting up and managing database servers. A softer requirement was that the database have either a pure D interface, or an easy-to-use wrapper on top of a C binding. Dealing with a C API and translating from database types to D types would just be too distracting. Fortunately, one database and API combo was found that meets both requirements exceedingly well.

sqlite3 is a popular and easy-to-use library for embeddable databases that can exist in memory or on disk. There are no executables required and no server connections to configure and launch; it can be used just like any other C library. There is also no need to set up database users or create a database with SQL. Databases are created programmatically when the app launches. Tables still need to be created with SQL statements, but it is easy to do this during initialization.

d2sqlite3 (http://code.dlang.org/packages/d2sqlite3) is a library that provides both a binding and a wrapper for sqlite3. The wrapper provides a convenient interface over the C API, including a range-based interface to the result sets returned by database queries. It takes just a few lines to get a database created and ready for use, and queries can also be implemented concisely and cleanly.

Note

Phobos ships with an sqlite3 binding in the etc.c.sqlite3 module, but it is often a few releases behind the official sqlite3 distribution. The binding in d2sqlite3 is updated more frequently.

The only downside to d2sqlite3 is its unavoidable dependency on the sqlite3 C library. Linux and Mac users should be able to easily get the development version of the library through their system package manager and, if not, the sqlite3 download page at https://www.sqlite.org/download.html has binaries for multiple platforms. It's quite possible that your system package manager has an older version of the library that will not compile with MovieManWeb, in which case you'll need to download and install the binaries for your platform or compile from source yourself. The d2sqlite3 project configuration has a directive telling DUB to link with the sqlite3 library, so nothing need be done beyond installing the binaries where the linker can find them. On Windows, it's a different story entirely.

The sqlite3 download page provides a ZIP file with a precompiled 32-bit DLL. By itself, this isn't actually very useful for DMD users. Some work needs to be done to get an import library in the appropriate object file format. To make things easier, I've generated a 32-bit import library in OMF format for the default DMD linker, and have compiled 32-bit and 64-bit static libraries in COFF for those who want to compile with the -m64 and -m32mscoff compiler switches. To hide all of this, a few version statements and a pragma can be added to one of the source modules. We're getting a bit ahead of ourselves here, though, as we haven't yet set up the MovieManWeb project. That's right around the corner in the next section, so let's get to it.

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

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