epubjs
Version:
Render ePub documents in the browser, across many devices
509 lines (471 loc) • 79 kB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Chapter 7. Important External Modules</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="chapter" title="Chapter 7. Important External Modules"><div class="titlepage"><div><div><h1 class="title"><a id="chapter_10"/>Chapter 7. Important External Modules</h1></div></div></div><p>Although the Node core is extremely useful, many of its abstractions
are very low-level. So a lot of development in Node is done using higher
abstraction libraries built by the community, similar to how Ruby-based
websites use Rails or Sinatra rather than custom-written Ruby code. Although these
modules aren’t technically Node itself, they are extremely important for
getting things done, and many of them are mature projects in themselves.
This chapter explores some of the most popular and useful community modules
for Node.</p><div class="sect1" title="Express"><div class="titlepage"><div><div><h1 class="title"><a id="I_sect14_d1e11765"/>Express</h1></div></div></div><p>Express, an <a id="ex7.1" class="indexterm"/>MVC framework for Node, is probably the most widely used
Node module. It was inspired by the Sinatra framework for Ruby and enables
a lot of features that make it very easy to throw together a website with
Node.</p><div class="sect2" title="A Basic Express App"><div class="titlepage"><div><div><h2 class="title"><a id="id844032"/>A Basic Express App</h2></div></div></div><p>Express works by defining page handlers for
<em class="firstterm">routes</em>. The routes can be as simple as a path, or
much more complex. The handlers could be as simple as emitting “Hello,
world” or as complex as a whole page-rendering system that interacts
with a database. You’ll need to install Express using <code class="literal">npm install express</code> before <a id="I_indexterm4_d1e11787" class="indexterm"/><a id="I_indexterm4_d1e11792" class="indexterm"/>you can start using it. <a class="xref" href="ch07.html#example7-1" title="Example 7-1. Creating a simple Express app">Example 7-1</a>
shows how to create a simple application with Express.</p><div class="example"><a id="example7-1"/><p class="title">Example 7-1. Creating a simple Express app</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer();
app.get('/', function(req, res) {
res.send('hello world');
});
app.listen(9001);</pre></div></div><p>This code is obviously pretty similar to <code class="literal">http</code> in <a id="I_indexterm4_d1e11810" class="indexterm"/><a id="I_indexterm4_d1e11815" class="indexterm"/>terms of creating a server. However, a few things are a
lot more straightforward. First, <code class="literal">app.get()</code> is creating a response to a specific
route—in this case, <code class="literal">'/'</code>. Unlike a
regular <code class="literal">http</code> server, which provides a
listener for generic requests, Express offers a listener for specific
HTTP verbs. So <code class="literal">get()</code> will answer only
<a id="I_indexterm4_d1e11834" class="indexterm"/>GET requests, <code class="literal">put()</code>
will answer only PUT requests, etc. Combine that with the route we
specified, and you immediately have some powerful functionality. A
typical Express program specifies a series of expressions, and Express
matches the route in each incoming request against each expression in
turn, executing the code associated with the first expression that
matches.</p><div class="note" title="Note"><h3 class="title">Note</h3><p>It is possible to have Express skip over expressions under
certain conditions, using the <code class="literal">next()</code> function discussed later in this
section.</p></div><p>The next thing to notice in the example is how we responded. We
still use the <code class="literal">response</code> object as in
<code class="literal">http</code>, but Express has provided a
<code class="literal">send()</code> <a id="I_indexterm4_d1e11858" class="indexterm"/>method. We didn’t need to provide any HTTP headers or call
<code class="literal">end()</code>. The <code class="literal">send()</code> method figures out things such as the
HTTP headers that should be sent and includes <code class="literal">end()</code> automatically.</p><p>The point here is that Express takes the basic structure laid out
by <code class="literal">http</code> and enriches it significantly
with a lot of functionality to create real applications quickly. You
shouldn’t have to create routing code every time you want to deal with
HTTP requests, so Express takes care of that <a id="I_indexterm4_d1e11879" class="indexterm"/>stuff.</p></div><div class="sect2" title="Setting Up Routes in Express"><div class="titlepage"><div><div><h2 class="title"><a id="settinguproutes_with_express"/>Setting Up Routes in Express</h2></div></div></div><p>Routes are one of the <a id="ex7.1.2" class="indexterm"/><a id="ro7.1.2" class="indexterm"/>core concepts in Express, and one of the things that make
it really useful. As mentioned in the previous section, routes are
applied to an HTTP verb via a method with the same name, such as
<code class="literal">get()</code> or <code class="literal">post()</code>. The routes consist of a simple string
or a regex and can contain variable declarations, wildcards, and
optional key flags. Let’s take a look at some examples, starting with
<a class="xref" href="ch07.html#example7-2" title="Example 7-2. Route with variable and optional flag">Example 7-2</a>.</p><div class="example"><a id="example7-2"/><p class="title">Example 7-2. Route with variable and optional flag</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer();
app.get('/:id?', function(req, res) {
if(req.params.id) {
res.send(req.params.id);
} else {
res.send('oh hai');
}
});
app.listen(9001);</pre></div></div><p>This example shows a route that includes an optional variable
called <code class="literal">id</code>. The variable name does not
have any special meaning to Express, but it will be available to use
inside the callback function. In Express routes, you use a preceding
colon (<code class="literal">:</code>) to mark a variable you want
preserved. The string passed in the URL will be captured into the
variable. All routes in Express are actually turned into regular
expressions (more on this later) and tokenized<sup>[<a id="id844306" href="#ftn.id844306" class="footnote">16</a>]</sup> for use by application code.<sup>[<a id="id844314" href="#ftn.id844314" class="footnote">17</a>]</sup> The regex used will match up to the next known token in
your route. Notice that this variable is also optional. If you run this
program and go to <span class="emphasis"><em>http://localhost:9001</em></span>, you’ll
just get “oh hai” back because you did not put a slash after the port,
and the variable part of the route was optional. If you append anything
else (so long as you don’t include another <code class="literal">/</code>), you’ll get it back as your response body;
matching the <code class="literal">id</code> token, it will be
stored in <code class="literal">req.params.id</code>.</p><p>Express routes will always treat <code class="literal">/</code> as a token, but they will also treat it as
optional if it terminates the request. So our route <code class="literal">/:id?</code> will match <code class="literal">localhost</code>, <code class="literal">localhost/</code> <code class="literal">localhost/tom</code>, and <code class="literal">localhost/tom/</code>, but <span class="emphasis"><em>not</em></span>
<code class="literal">localhost/tom/tom</code>.</p><p>Routes can also use wildcards, as shown in <a class="xref" href="ch07.html#example7-3" title="Example 7-3. Using wildcards in routes">Example 7-3</a>. (<code class="literal">*</code>) will
match anything <a id="I_indexterm4_d1e11982" class="indexterm"/><a id="I_indexterm4_d1e11987" class="indexterm"/>except the token following it (nongreedy regex
matching).</p><div class="example"><a id="example7-3"/><p class="title">Example 7-3. Using wildcards in routes</p><div class="example-contents"><pre class="programlisting">app.get('/a*', function(req,res) {
res.send('a');
//matches /afoo /a.bar /a/qux etc.
});
app.get('/b*/c*d', function(req,res) {
res.send('b');
//matches /b/cd /b/cfood /b//c/d/ etc.
//does not match /b/c/d/foo
});
app.get('*', function(req, res) {
res.send('*');
//matches /a /c /b/cd /b/c/d /b/c/d/foo
//does not match /afoo /bfoo/cbard
});</pre></div></div><p>When you use a wildcard to make routes, any tokens between the
wildcards must match, unless they are optional. Wildcards are often used
for things such as filenames containing periods (<code class="literal">.</code>). It’s also important to notice that unlike
in many regular expression languages, <code class="literal">*</code> does not mean zero or more characters; it
means one or more characters. A forward slash (<code class="literal">/</code>) can be considered a character when matching
with wildcards.</p><p>Another important thing to note is that routes are ordered.
Multiple routes can match a given URL, but only the first one that
matches will trigger the associated activity. This means that the order
in which routes are defined is very significant. In the previous
example, the general wildcard will catch everything that wasn’t already
caught by a previous route, even though it matches all of them.</p><p>You can also use<a id="I_indexterm4_d1e12012" class="indexterm"/> regexes to define routes (<a class="xref" href="ch07.html#example7-4" title="Example 7-4. Using a regex to define a route">Example 7-4</a>).
If you do this, <code class="literal">router</code> won’t process
the regex any further. Because you still might want to get variables out
of the URL, you can use captures to define them.</p><div class="example"><a id="example7-4"/><p class="title">Example 7-4. Using a regex to define a route</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer();
app.get(/\/(\d+)/, function(req, res) {
res.send(req.params[0]);
});
app.listen(9001);</pre></div></div><p>In this example, the regex will match only URLs that start with a
number (<code class="literal">\d</code> matches any digit, and the
<code class="literal">+</code> allows one or more to match). This
means that <code class="literal">/</code> will not match, but
<code class="literal">/12</code> will. However, the regex checking
uses<a id="I_indexterm4_d1e12043" class="indexterm"/> <code class="literal">RegExp.match()</code>, which
finds a regex inside a larger string. This means that <code class="literal">/12abc</code> will also match. If you want to make
sure that a regex represents the complete route, use the <code class="literal">$</code> token at the end of the regex, such as
<code class="literal">/\/(\d+)$/</code>. <code class="literal">$</code> checks for the end of the line, so the regex
will match only if it terminates. You probably want to keep the default
Express behavior of loosely matching a <code class="literal">/</code> at the end of URLs, though. Do this with
<code class="literal">\/?$</code> instead of just <code class="literal">$</code>, to allow an optional <code class="literal">/</code> at the end of the string.</p><p>Notice how we accessed the capture in our regex in <a class="xref" href="ch07.html#example7-4" title="Example 7-4. Using a regex to define a route">Example 7-4</a>. If you use a regex for your route, you can use
<code class="literal">req.params</code> as an array to access the
captures as variables. This also works when <code class="literal">router</code> converts your route to a regex, but you
probably want to use the variable names in that case, as we showed
earlier. You can also use regex to make better-named variables in routes
by constraining what will match that variable, as in <a class="xref" href="ch07.html#example7-5" title="Example 7-5. Use regex to be more specific about variable types">Example 7-5</a>.</p><div class="example"><a id="example7-5"/><p class="title">Example 7-5. Use regex to be more specific about variable types</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer();
app.get('/:id(\\d+)', function(req, res) {
res.send(req.params[0]);
});
app.listen(9001);</pre></div></div><p>This example constrains the <code class="literal">id</code>
parameter to numbers by asking <code class="literal">route</code>
to match only numbers with the regex <code class="literal">\d+</code>. The capture will still be exposed as
<code class="literal">req.params.id</code>, but it will match only
if the regex matched. Because the regex is highly flexible, you can use
this technique to capture or restrict URL matching to pretty much
anything while still getting named variables to use. Remember to escape
any backslash (<code class="literal">\</code>) you use in
JavaScript strings. (This was not necessary in <a class="xref" href="ch07.html#example7-4" title="Example 7-4. Using a regex to define a route">Example 7-4</a>, because it used a regular expression directly
rather than inside a string.)</p><p>Sometimes there are multiple routes that match a URL that you want
to use in various circumstances. We’ve already seen that the order in
which routes are defined is significant in determining which will be
selected. However, it is possible to pass control back to the next route
if some criteria isn’t met (<a class="xref" href="ch07.html#example7-6" title="Example 7-6. Passing control to another route">Example 7-6</a>). This is a
great option for a <a id="I_indexterm4_d1e12119" class="indexterm"/>number of scenarios.</p><div class="example"><a id="example7-6"/><p class="title">Example 7-6. Passing control to another route</p><div class="example-contents"><pre class="programlisting">app.get('/users/:id', function(req, res, next){
var id = req.params.id;
if (checkPermission(id)) {
// show private page
} else {
next();
}
});
app.get('/users/:id', function(req, res){
// show public user page
});</pre></div></div><p>We’ve added another argument to the function that handles the
routes. The <code class="literal">next</code> argument tells the
<code class="literal">router</code> middleware (we’ll discuss
middleware shortly in more depth) <a id="I_indexterm4_d1e12138" class="indexterm"/>to call the next route. The argument is always passed to
the callback, but this example is the first where we choose to name and
use it. In this case, we can check the <code class="literal">id</code> to see whether the user has permission to
view the private version of this page, and if not, send her to the next
route, which has the public version.</p><p>This combines really well with <code class="literal">app.all()</code>, the method that describes all HTTP
verbs. As <a class="xref" href="ch07.html#example7-7" title="Example 7-7. Using app.all( ) to select multiple HTTP verbs and routes and then pass control back">Example 7-7</a> demonstrates, we can capture
across a range of HTTP verbs and routes, apply some logic, and then pass
control onto more specific routes.</p><div class="example"><a id="example7-7"/><p class="title">Example 7-7. Using app.all( ) to select multiple HTTP verbs and routes and
then pass control back</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer();
var users = [{ name: 'tj' }, { name: tom }];
app.all('/user/:id/:op?', function(req, res, next){
req.user = users[req.params.id];
if (req.user) {
next();
} else {
next(new Error('Cannot find user with ID: ' + req.params.id));
}
});
app.get('/user/:id', function(req, res){
res.send('Viewing ' + req.user.name);
});
app.get('/user/:id/edit', function(req, res){
res.send('Editing ' + req.user.name);
});
app.put('/user/:id', function(req, res){
res.send('Updating ' + req.user.name);
});
app.get('*', function(req, res){
res.send('Danger, Will Robinson!', 404);
});
app.listen(3000);</pre></div></div><p>This example is similar to <a class="xref" href="ch07.html#example7-6" title="Example 7-6. Passing control to another route">Example 7-6</a>, in that
we are validating whether a user exists before passing on control.
However, we are not doing this only for all the subsequent routes; we
are also doing it across all HTTP verbs. Normally when only one route
matches, this doesn’t make any difference, but it’s important to note
how you can pass state between routes.</p><p>When the <code class="literal">req.user</code> attribute is
added in the <code class="literal">app.all()</code> method, it is
available in all the subsequent methods because the middleware owns the
request object. When each callback is fired, the variable <code class="literal">.req</code> is really a pointer to the request object
owned by the middleware, and any changes to the request object are
visible to every other function and route using the middleware.</p><p><a class="xref" href="ch07.html#example7-8" title="Example 7-8. Optional and required route extensions">Example 7-8</a> shows how a file extension can be
made either optional or mandatory within a specific range. In the first
<code class="literal">get()</code>, the <code class="literal">:format</code> parameter is optional (as denoted by
the question mark), so Express will respond to requests for a user by
ID, regardless of which format has been requested. It is up to the
programmer to capture the formats (JSON, XML, text, etc.) via a switch
statement in order to do special processing.</p><p>In the second example, the <code class="literal">:format</code> parameter
looks for <code class="literal">json</code> or <code class="literal">xml</code> as predefined file types. If those are not
found, the book request will not be processed, regardless of whether the
<code class="literal">:id</code> parameter is valid. This gives us
greater control over which requests are responded to and ensures that
only formats for which a view can be generated are available to
<a id="I_indexterm4_d1e12198" class="indexterm"/><a id="I_indexterm4_d1e12200" class="indexterm"/>respond.</p><div class="example"><a id="example7-8"/><p class="title">Example 7-8. Optional and required route extensions</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer();
app.get('/users/:id.:format?', function(req, res) {
res.send(req.params.id + "<br/>" + req.params.format);
// Responds to:
// /users/15
// /users/15.xml
// /users/15.json
});
app.get('/books/:id.:format((json|xml))', function(req, res) {
res.send(req.params.id + "<br/>" + req.params.format);
// Responds to:
// /books/7.json
// /books/7.xml
// But NOT to:
// /books/7
// /books/7.txt
});
app.listen(8080);</pre></div></div></div><div class="sect2" title="Handling Form Data"><div class="titlepage"><div><div><h2 class="title"><a id="id844872"/>Handling Form Data</h2></div></div></div><p>Most examples have <a id="I_indexterm4_d1e12213" class="indexterm"/>demonstrated the GET verb, but Express is built to support
RESTful architecture in the style of Ruby on Rails. Using hidden fields
inside web forms, you can indicate whether a form’s intention <a id="I_indexterm4_d1e12219" class="indexterm"/>is to PUT (replace data), POST <a id="I_indexterm4_d1e12223" class="indexterm"/>(create data), <a id="I_indexterm4_d1e12227" class="indexterm"/>DELETE (remove data) or <a id="I_indexterm4_d1e12231" class="indexterm"/>GET (retrieve data). See <a class="xref" href="ch07.html#example7-9" title="Example 7-9. Handling forms using Express">Example 7-9</a>.</p><div class="example"><a id="example7-9"/><p class="title">Example 7-9. Handling forms using Express</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer();
app.use(express.limit('1mb'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.get('/', function(req, res) {
res.send('<form method="post" action="/">' +
'<input type="hidden" name="_method" value="put" />' +
'Your Name: <input type="text" name="username" />' +
'<input type="submit" />' +
'</form>');
});
app.put('/', function(req, res) {
res.send('Welcome, ' + req.body.username);
});
app.listen(8080);</pre></div></div><p>This simple application demonstrates the use of a form. First, an
Express application is created and configured to use the <code class="literal">bodyParser()</code> and <code class="literal">methodOverride()</code> functions. The <code class="literal">bodyParser()</code> function <a id="I_indexterm4_d1e12254" class="indexterm"/><a id="I_indexterm4_d1e12259" class="indexterm"/><a id="I_indexterm4_d1e12264" class="indexterm"/><a id="I_indexterm4_d1e12267" class="indexterm"/>parses the request body sent by the web browser and
translates form variables into objects usable by Express. The <code class="literal">methodOverride()</code> function allows the hidden
<code class="literal">_method</code> variable in form posts to
override the GET method in favor of the RESTful method types.</p><p>The <code class="literal">express.limit()</code> <a id="I_indexterm4_d1e12283" class="indexterm"/>function instructs Express to limit the length of request
bodies to 1 MB. This is an important security consideration because
otherwise it would be possible to send a large post to the application
to be processed by <code class="literal">bodyParser()</code>,
making it very easy to launch a <a id="I_indexterm4_d1e12292" class="indexterm"/><a id="I_indexterm4_d1e12295" class="indexterm"/>denial-of-service (DoS) attack.</p><div class="note" title="Note"><h3 class="title">Note</h3><p>Be sure to call <code class="literal">methodOverride()</code> after <code class="literal">bodyParser()</code>. Otherwise, the form variables
will not be processed when Express checks to see whether it should be
responding to a GET or some other command.</p></div></div><div class="sect2" title="Template Engines"><div class="titlepage"><div><div><h2 class="title"><a id="id845066"/>Template Engines</h2></div></div></div><p>Clearly, it isn’t <a id="ex7.1.4" class="indexterm"/><a id="te7.1.4" class="indexterm"/>practical to continue writing HTML directly in application
code. For starters, it is unreadable and unmaintainable; but more
importantly, it is bad form to mix application logic with presentation
markup. Template engines allow developers space to focus on how to
present information to the user—often in different formats, such as
screen or mobile—and inject specific data separately from
processing.</p><p>Express is minimalist and does not come with built-in template
engines, opting instead for community-supported modules. Some of the
more popular engines <a id="I_indexterm4_d1e12326" class="indexterm"/><a id="ja7.1.4" class="indexterm"/><a id="I_indexterm4_d1e12332" class="indexterm"/><a id="I_indexterm4_d1e12335" class="indexterm"/><a id="I_indexterm4_d1e12338" class="indexterm"/>are Haml, Jade, Embedded Javascript (EJ), CoffeeKup (a
CoffeeScript-based engine), <a id="I_indexterm4_d1e12342" class="indexterm"/>and jQuery templates.</p><p>In <a class="xref" href="ch07.html#example7-10" title="Example 7-10. Using a basic Jade template in Express">Example 7-10</a>, an application is set up to
render a simple Jade template.</p><div class="example"><a id="example7-10"/><p class="title">Example 7-10. Using a basic Jade template in Express</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer();
app.get('/', function(req, res) {
res.render('index.jade', { pageTitle: 'Jade Example', layout: false });
});
app.listen(8080);</pre></div></div><p>To run this example, you will need to install the Jade template
engine:</p><a id="I_programlisting4_d1e12360"/><pre class="programlisting">npm install jade</pre><p>The first thing to notice is the lack of any reference to the Jade
library. Express parses the view template’s filename and uses the
extension (in this case, the <code class="literal">jade</code>
from <em class="filename">index.jade</em>) to determine which
<a id="I_indexterm4_d1e12371" class="indexterm"/>view engine should be used. Therefore, it is possible to
mix and match different view engines into the same project. You are not
limited to using only Jade or only CoffeeKup, for example; you can use
both.</p><p>This example passes two arguments into the render function. The
first is the name of the view to display, and the second contains
options and variables needed for the rendering. We’ll come back to the
filename in a minute. There are two variables passed into the view in
this example: <code class="literal">pageTitle</code> and <code class="literal">layout</code>. The <code class="literal">layout</code> variable
is interesting in this case because it is set to <code class="literal">false</code>, which instructs the Jade view engine to
render the contents of <em class="filename">index.jade</em>
without first going through a master layout file (more on this
later).</p><p><code class="literal">pageTitle</code> is a local variable
that will be consumed by the contents of the view. It represents the
point of templating: whereas the HTML is specified mostly in <em class="filename">index.jade</em> file, that file has a placeholder
named <code class="literal">pageTitle</code> where Jade will plug
in the value we provide.</p><p>The file (<em class="filename">index.jade</em>) from
the first parameter needs to be placed in the <em class="filename">views</em> folder (<em class="filename">/views/index.jade</em>) and looks like <a class="xref" href="ch07.html#example7-11" title="Example 7-11. A basic Jade file for Express">Example 7-11</a>.</p><div class="example"><a id="example7-11"/><p class="title">Example 7-11. A basic Jade file for Express</p><div class="example-contents"><pre class="programlisting">!!! 5
html(lang="en")
head
title =pageTitle
body
h1 Hello, World
p This is an example of Jade.</pre><p>After Jade plugs in the value for <code class="literal">pageTitle</code> that we supplied, the page renders
as:</p><pre class="programlisting"><!DOCTYPE html>
<html lang="en">
<head>
<title>Jade Example</title>
</head>
<body>
<h1>Hello, World</h1>
<p>This is an example of Jade.</p>
</body>
</html></pre></div></div><p>The Jade template aims to make the page more succinct by paring
down the markup to the bare minimum. Instead of the closing tags you may
be accustomed to in HTML, Jade uses indentation to communicate position
within the page’s hierarchy, resulting in a clean and generally
easy-to-read file.</p><p>The very first line, <code class="literal">"!!! 5"</code>,
identifies the content type as HTML5, manifesting as an HTML5 doctype in
the resulting output. The default document types supported by Jade are
<code class="literal">5</code>, <code class="literal">xml</code>, <code class="literal">default</code> (which is XHTML 1.0 Transitional),
<code class="literal">transitional</code> (the default), <code class="literal">strict</code>, <code class="literal">frameset</code>, <code class="literal">1.1</code>, <code class="literal">basic</code>,
and <code class="literal">mobile</code>. You can supply your own,
though, such as <code class="literal">doctype html PUBLIC
"-//W3C//DATA XHTML Custom 1.10a//DE"</code>.</p><p>Look in the <code class="literal">title</code> tag on the
fourth line of the Jade input. The string <code class="literal">=pageTitle</code> is interpreted by Jade as “insert
the contents of the variable named <code class="literal">pageTitle</code> here.” In the resulting output, this
becomes <code class="literal">Jade Example</code>, the value
provided by the previous application code.</p><p>As we mentioned, there are many other templating options, each of
which does essentially what Jade does, but with different syntax
<a id="I_indexterm4_d1e12484" class="indexterm"/><a id="I_indexterm4_d1e12486" class="indexterm"/>and conventions.</p><div class="sect3" title="Layouts and partial views"><div class="titlepage"><div><div><h3 class="title"><a id="id845428"/>Layouts and partial views</h3></div></div></div><p>Layouts allow views to share <a id="la7.1.4.1" class="indexterm"/><a id="te7.1.4.1" class="indexterm"/>common structural elements in your site, providing an
even greater separation of content and data. By standardizing parts of
the layout, such as navigation, header, and footer, you can focus your
development efforts on the actual content for each view.</p><p><a class="xref" href="ch07.html#example7-12" title="Example 7-12. Defining global template engines in Express">Example 7-12</a> takes the <a id="I_indexterm4_d1e12506" class="indexterm"/>view engine concept already discussed and turns it into
a “real” website.</p><div class="example"><a id="example7-12"/><p class="title">Example 7-12. Defining global template engines in Express</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer();
app.set('view engine', 'jade');
app.get('/', function(req, res) {
res.render('battlestar')
});</pre></div></div><p>New to this example is the <code class="literal">set</code> command on the “view engine” parameter.
The Jade view engine will now be considered the default by Express,
although it is still possible to override it in the render
method.</p><p>The render function is markedly different. Because the Jade
engine has been set as the default view engine, this example does not
need to specify the full filename, so <code class="literal">battlestar</code> actually refers to <em class="filename">/views/battlestar.jade</em>. The <code class="literal">layout: false</code> parameter from <a class="xref" href="ch07.html#example7-10" title="Example 7-10. Using a basic Jade template in Express">Example 7-10</a> is no longer needed, because this time
Express will be making use of this layout file located at <em class="filename">views/layout.jade</em>, shown in <a class="xref" href="ch07.html#example7-13" title="Example 7-13. A Jade layout file in Express">Example 7-13</a>.</p><div class="example"><a id="example7-13"/><p class="title">Example 7-13. A Jade layout file in Express</p><div class="example-contents"><pre class="programlisting">html
body
h1 Battlestar Galactica Fan Page
!= body</pre></div></div><p>The layout file is very similar to the view file created
earlier, but in this case there is a special <code class="literal">body</code> variable. We’re talking here about the
<code class="literal">!= body</code> line; please don’t
confuse that with the <code class="literal">body</code> keyword
near the top of the file. The second <code class="literal">body</code> is not the name of a variable passed in
through the application code, so where does it come from?</p><p>When the <code class="literal">layout</code> option is set
to <code class="literal">true</code> (the default) in Express,
the <code class="literal">render</code> method works by parsing
the contents of the first parameter and passing the rendered output to
the layout as a variable called <code class="literal">body</code>. The <em class="filename">battlestar.jade</em> file looks like <a class="xref" href="ch07.html#example7-14" title="Example 7-14. A Jade partial view in Express">Example 7-14</a>.</p><div class="example"><a id="example7-14"/><p class="title">Example 7-14. A Jade partial view in Express</p><div class="example-contents"><pre class="programlisting">p Welcome to the fan page.</pre></div></div><p>This is called a partial view because it does not contain the
full content needed to generate a page, and it needs to be combined
with a layout to become useful output. The final web browser output
for all this work looks like this:</p><a id="I_programlisting4_d1e12588"/><pre class="programlisting"><html>
<body>
<h1>Battlestar Galactica Fan Page</h1>
<p>Welcome to the fan page.</p>
</body>
</html></pre><p>Partial views are powerful because they allow developers to
focus on the specific content being displayed, rather than the web
page as a whole. This means the contents don’t have to be tied to a
web page and can be output to mobile web pages, AJAX requests (for
in-place page refreshes), and <a id="I_indexterm4_d1e12592" class="indexterm"/><a id="I_indexterm4_d1e12594" class="indexterm"/><a id="I_indexterm4_d1e12596" class="indexterm"/>more.</p><div class="warning" title="Warning"><h3 class="title">Warning</h3><p>Be careful not to confuse the variable named <code class="literal">body</code>, which contains the actual content of
your view, with the keyword <code class="literal">body</code>,
which is an HTML tag used by the web browser.</p></div></div></div><div class="sect2" title="Middleware"><div class="titlepage"><div><div><h2 class="title"><a id="id845674"/>Middleware</h2></div></div></div><p>Some of the examples up to this point have included a rather
innocuous-looking function: <code class="literal">app.use()</code>. This function
invokes the Connect library <a id="co7.1.5" class="indexterm"/><a id="I_indexterm4_d1e12619" class="indexterm"/>and exposes many powerful tools that make it simple to add
functionality. Now it's time to take a step back and examine what all
this glue—known as middleware—is,<a id="ex7.1.5" class="indexterm"/><a id="mi7.1.5" class="indexterm"/> and why it is so important to developing with
Express.</p><p>Although it might sound like one of those obscure buzzwords that
programmers like to use when they want to appear “in the know,”
middleware—as we’ve mentioned in previous chapters—refers to a piece of
software that acts as a link between two other programs, typically
between a higher-level application and a wider network. In the real
world, middleware is analogous to the telephone lines you might find in
your home or office building. All telephones (applications) connect to
the same telephone lines (middleware), which in turn broker
communication from the application to the underlying network.</p><p>Your phone may or may not support call waiting or voicemail, but
the line behaves the same, regardless of which features are available to
you. You may have voicemail built into your phone, or it may be provided
by your telco (network); in either case, the line itself is happy to
support your usage.</p><p>Connect provides the middleware functionality used by Express (see
<a class="xref" href="ch07.html#table7-1" title="Table 7-1. Middleware bundled with Connect">Table 7-1</a>). As shown in <a class="xref" href="ch07.html#express_middleware_stack" title="Figure 7-1. Express’s middleware stack">Figure 7-1</a>, Connect extends Node’s <a id="I_indexterm4_d1e12649" class="indexterm"/>base <code class="literal">http</code> module, giving it all of the
base capabilities provided by <code class="literal">http</code>, upon which it
adds its own functionality. Express in turn inherits from Connect,
gaining its abilities and, by extension, <code class="literal">http</code>’s as
well. Any module plugged into
Connect is automatically made available to Express. Connect is the
middle layer between Express and the network, and as such exposes and
uses a myriad of features that may not be used directly by Express, but
are available all the same. Finally, because Express derives itself from
Connect, most of Connect’s functionality is available directly from
Express, allowing you to issue commands such as
<code class="literal">app.bodyParser()</code> rather than
<code class="literal">connect.bodyParser()</code>.</p><div class="figure-float"><div class="figure"><a id="express_middleware_stack"/><div class="figure-contents"><div class="mediaobject"><a id="I_mediaobject4_d1e12677"/><img src="httpatomoreillycomsourceoreillyimages1137985.png" alt="Express’s middleware stack"/></div></div><p class="title">Figure 7-1. Express’s middleware stack</p></div></div><div class="table"><a id="table7-1"/><p class="title">Table 7-1. Middleware bundled with Connect</p><div class="table-contents"><table summary="Middleware bundled with Connect" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col/><col/></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; ">Name</th><th style="border-bottom: 0.5pt solid ; ">Description</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">basicAuth</code></td><td style="border-bottom: 0.5pt solid ; ">Accepts a <a id="I_indexterm4_d1e12699" class="indexterm"/>callback function that accepts username and
password parameters, then returns true if the credentials are
permitted access to the site.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">bodyParser</code></td><td style="border-bottom: 0.5pt solid ; ">Parses <a id="I_indexterm4_d1e12709" class="indexterm"/>the contents of the request body.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">compiler</code></td><td style="border-bottom: 0.5pt solid ; ">Compiles <em class="filename">.sass</em> and
<em class="filename">.less</em> files <a id="I_indexterm4_d1e12725" class="indexterm"/><a id="I_indexterm4_d1e12728" class="indexterm"/>to <a id="I_indexterm4_d1e12732" class="indexterm"/>CSS and CoffeeScript files to JavaScript.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">.cookieParser</code></td><td style="border-bottom: 0.5pt solid ; ">Parses the <a id="I_indexterm4_d1e12742" class="indexterm"/>contents of cookies sent by the web browser in the
request headers.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">csrf</code></td><td style="border-bottom: 0.5pt solid ; ">Provides <a id="I_indexterm4_d1e12752" class="indexterm"/>cross-site request forgery (CSRF) <a id="I_indexterm4_d1e12756" class="indexterm"/><a id="I_indexterm4_d1e12759" class="indexterm"/>protection by mutating the request through an
additional form variable. Requires <code class="literal">session</code>
and <code class="literal">bodyParser</code> middleware.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">directory</code></td><td style="border-bottom: 0.5pt solid ; ">Prints <a id="I_indexterm4_d1e12775" class="indexterm"/>directory listings inside a root path, with
options to display hidden files and icons.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">errorHandler</code></td><td style="border-bottom: 0.5pt solid ; ">Traps <a id="I_indexterm4_d1e12785" class="indexterm"/>errors encountered by the application and provides
options to log errors to stderr or request output in multiple
formats (JSON, plain text, or HTML).</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">favicon</code></td><td style="border-bottom: 0.5pt solid ; ">Serves <a id="I_indexterm4_d1e12795" class="indexterm"/>favicon files from memory, with cache
control.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">limit</code></td><td style="border-bottom: 0.5pt solid ; ">Limits <a id="I_indexterm4_d1e12805" class="indexterm"/>the size of requests accepted by the server to
protect against DoS attacks.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">logger</code></td><td style="border-bottom: 0.5pt solid ; ">Logs <a id="I_indexterm4_d1e12815" class="indexterm"/>requests to output or a file, in multiple formats,
either on response (default) or on request. Optional buffer size
controls how many requests are collected before writing to
disk.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">methodOverride</code></td><td style="border-bottom: 0.5pt solid ; ">Combine <a id="I_indexterm4_d1e12825" class="indexterm"/>with <code class="literal">bodyParser</code> to provide
DELETE and PUT methods along with POST. Allows for more explicit
route definitions; for example, use <code class="literal">app.put()</code>
rather than detecting the user’s intention from
<code class="literal">app.post()</code>. This technique enables RESTful
application design.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">profiler</code></td><td style="border-bottom: 0.5pt solid ; ">Typically <a id="I_indexterm4_d1e12845" class="indexterm"/>placed before all other middleware,
<code class="literal">profiler</code> records the response time and memory
statistics for requests.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">query</code></td><td style="border-bottom: 0.5pt solid ; ">Parses <a id="I_indexterm4_d1e12858" class="indexterm"/>query strings and populates the
<code class="literal">req.query</code> parameter.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">responseTime</code></td><td style="border-bottom: 0.5pt solid ; ">Populates <a id="I_indexterm4_d1e12871" class="indexterm"/>the X-Response-Time header <a id="I_indexterm4_d1e12875" class="indexterm"/>with the time (in milliseconds) to generate a
response.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">router</code></td><td style="border-bottom: 0.5pt solid ; ">Provides <a id="I_indexterm4_d1e12885" class="indexterm"/>advanced routing (discussed in <a class="xref" href="ch07.html#settinguproutes_with_express" title="Setting Up Routes in Express">Setting Up Routes in Express</a>)</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">session</code></td><td style="border-bottom: 0.5pt solid ; ">The session <a id="I_indexterm4_d1e12897" class="indexterm"/>manager for persisting user data across
requests.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">static</code></td><td style="border-bottom: 0.5pt solid ; ">Enables <a id="I_indexterm4_d1e12909" class="indexterm"/>streaming of static files from a root directory.
Allows for partial downloads and custom expiry aging.</td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><code class="literal">staticCache</code></td><td style="border-bottom: 0.5pt solid ; ">Adds a <a id="I_indexterm4_d1e12919" class="indexterm"/>caching layer to the static middleware, keeping
the most popular downloaded files in memory for greatly improved
response times.</td></tr><tr><td style="border-right: 0.5pt solid ; "><code class="literal">vhost</code></td><td style="">Enables <a id="I_indexterm4_d1e12929" class="indexterm"/>multiple sites for <a id="I_indexterm4_d1e12933" class="indexterm"/>different vhosts on a <a id="I_indexterm4_d1e12936" class="indexterm"/>single machine.</td></tr></tbody></table></div></div><div class="sect3" title="Middleware factories"><div class="titlepage"><div><div><h3 class="title"><a id="id846307"/>Middleware factories</h3></div></div></div><p>By now you <a id="mi7.1.5.1" class="indexterm"/><a id="fa7.1.5.1" class="indexterm"/><a id="pa7.1.5.1" class="indexterm"/>may have noticed that middleware consists of little more
than functions that are executed sequentially by Express. JavaScript
closures give us a lot of power to implement the factory
pattern<sup>[<a id="id846347" href="#ftn.id846347" class="footnote">18</a>]</sup> inside Node, which can be exploited to provide
contextual functionality to your web routes.</p><p>Express’s routing <a id="I_indexterm4_d1e12967" class="indexterm"/><a id="I_indexterm4_d1e12972" class="indexterm"/>functions use internal middleware during their
processing cycle, which you can override to add extra
functionality—for example, to add custom headers to your HTML output.
Let’s look at <a class="xref" href="ch07.html#example7-15" title="Example 7-15. Middleware factories in Express">Example 7-15</a> and see how we can use a
middleware factory to intercept a page request and enforce role-based
authentication.</p><div class="example"><a id="example7-15"/><p class="title">Example 7-15. Middleware factories in Express</p><div class="example-contents"><pre class="programlisting">var express = require('express');
var app = express.createServer(
express.cookieParser(),
express.session({ secret: 'secret key' })
);
var roleFactory = function(role) {
return function(req, res, next) {
if ( req.session.role && req.session.role.indexOf(role) != -1 ) {
next(); } else {
res.send('You are not authenticated.');
}
}
};
app.get('/', roleFactory('admin'), function(req, res) {
res.send('Welcome to Express!');
});
app.get('/auth', function(req, res) {
req.session.role = 'admin';
res.send('You have been authenticated.');
});
app.listen(8080);</pre></div></div><p>Right off the bat, if you visit
<em class="filename">http://localhost:8080/</em> you will receive the
message “You are not authenticated.” However, if you look at the
contents of the route for<code class="literal"> '/'</code>, you will notice that
the actual page contents are <code class="literal">'Welcome to Express!'</code>.
The second parameter, <code class="literal">roleFactory('admin')</code>, launched before the
page was displayed and detected that there was no <code class="literal">role</code> property in your session, so it output
its own message and stopped the page execution.</p><p>If you visit <em class="filename">http://localhost:8080/auth</em>
followed by <em class="filename">http://localhost:8080/</em> you will
receive the “Welcome to Express!” message. In this circumstance, the
<em class="filename">/auth</em> URL attached the <code class="literal">'admin'</code>
variable to your session’s role property, so when
<code class="literal">roleFactory</code> was executed it passed the execution
control to <code class="literal">next()</code>, which is the
<code class="literal">app.get('/')</code> function.</p><p>Therefore, it could be said that by using internal middleware,
we changed the order of execution to:</p><div class="orderedlist"><ol class="orderedlist"><li class="listitem"><p><code class="literal">roleFactory('admin')</code></p></li><li class="listitem"><p><code class="literal">app.get('/')</code></p></li></ol></div><p>What if we wanted to authenticate based on more than one role?
In that case, we could change the route to:</p><a id="I_programlisting4_d1e13041"/><pre class="programlisting">var powerUsers = [roleFactory('admin'),roleFactory('client')];
app.get('/', powerUsers, function(req, res) {
res.send('Welcome to Express!');
});</pre><p>Because we passed an array as the middleware, we