• No results found

STATIC MIDDLEWARE

Static middleware is probably among the most common type of middleware you will use

during the development of web applications with Node.

Mounting

Connect allows middleware to be mounted to specific URLs. For middleware like static,

this can be really useful because it allows you to map an arbitrary URL to any directory in your filesystem.

For example, assume you want to serve a directory called /images when the URL /my- images is requested. You can do it with mounting:

128

PA R T I I I • Web Development

maxAge

The static middleware takes an option called maxAge that specifies how long a certain

resource can be cached in the client’s user agent. This capability is useful when you know a certain asset is not going to change, and you don’t want the user’s browser to re-request it. For example, it’s common practice for web applications to bundle up all the client-side JavaScript into a file that represents a revision number. You can add the maxAge option to

ensure those get cached forever:

server.use(‘/js’, connect.static(‘/path/to/bundles’, { maxAge: 10000000000000 });

hidden

The other option static takes is hidden. If this option is set to true, Connect serves files

that begin with a dot (.) and are considered hidden in Unix filesystems:

server.use(connect.static(‘/path/to/resources’, { hidden: true });

QUERY

Sometimes in your applications you have optional data associated with a URL that you send as part of the query string.

For example, consider the url/blog-posts?page=5. If you point your browser to that

URL, then Node populates req.url with a string:

server.use(function (req) {

// req.url == “/blog-posts?page=5” });

Most likely, though, you actually want to access the value contained in that querystring. If you implement the query middleware, you get a req.query object automatically with

those values:

server.use(connect.query); server.use(function (req, res) { // req.query.page == “5” });

Again, parsing the query string is a common task for applications that Connect greatly simplifies. Just as in the static example where you stopped including the require call for

the fs module, you no longer need to worry about using the querystring module.

This middleware is included automatically for you in Express, the web framework subject of the next chapter. Another very useful middleware is logger, which is described next.

C H A P T E R 8 • Connect

129

LOGGER

The logger middleware is a useful diagnostics tool for your web application. It prints out

information about incoming requests and outgoing responses to the terminal. There are different built-in logging formats you can use

◾ default ◾ dev ◾ short ◾ tiny

For example, in order to leverage the dev logger format you would initialize the logger

middleware as follows:

server.use(connect.logger(‘dev’));

Consider the following example, a typical “Hello World” HTTP server with the logger middleware in use:

var connect = require(‘connect’); connect.createServer(

connect.logger(‘dev’) , function (req, res) { res.writeHead(200); res.end(‘Hello world’); }

).listen(3000);

Notice that I passed a series of middleware functions as parameters to the createServer

helper function. This is equivalent to initializing a Connect server and calling use twice.

When you go to http://127.0.0.1:3000 in your browser, you’ll notice two lines get

output:

GET / 200 0ms

GET /favicon.ico 200 2ms

The browser is requesting /favicon.ico and /, and the connect logger is displaying the

method for the request, in addition to the response status code, and how long the process took.

dev is a concise and short logging format, giving you insight into behavior and performance

while you’re testing out your web apps.

130

PA R T I I I • Web Development

Say you want to log only the method and the IP:

server.use(connect.logger(‘:method :remote-addr’));

You can also log headers by using the dynamic tokens req and res. To log the content- length and the content-type of the response along with how long it took to produce,

you use the following:

server.use(connect.logger(‘type is :res[content-type], length is ‘ + ‘:res[content-length] and it took :response-time ms.’));

Note: Remember that, in Node, request/response headers are always lowercase.

If you apply it to the original website that requests four images, you can see some interesting output, as shown in Figure 8-6. (Make sure you request on a fresh cache and clear your browser data prior to running the example.)

Figure 8-6: Your custom logger in action

Following is the complete list of tokens you can use:

◾ :req[header] (for example, :req[Accept])

◾ :res[header] (for example, :res[Content-Length]) ◾ :http-version ◾ :response-time ◾ :remote-addr ◾ :date ◾ :method ◾ :url ◾ :referrer ◾ :user-agent ◾ :status

C H A P T E R 8 • Connect

131

You can also define custom tokens. Say you want a shortcut called :type that refers to the Content-Type of the request; in that case, you use the following:

connect.logger.token(‘type’, function (req, res) { return req.headers[‘content-type’];

});

The next middleware to consider is body parser, which automates another task you’ve been manually writing for http servers so far.