Below here is a partial copy of the documentation found at http://expressjs.com/guide.html; functionality that makes sense on the client but isn't implemented yet will clearly be marked.
To create an instance of the Client Express Server, simply invoke the createServer() method. With our instance server we can then define routes based on the HTTP verbs, in this example server.get().
var server = require('express').createServer(); server.get('/', function(request, response){ response.send('hello world'); }); server.listen();
Express supports arbitrary environments, such as production and development. Developers can use the configure() method to setup needs required by the current environment. When configure() is called without an environment name it will be run in every environment. The configure functions are being called in the order they where defined.
In the example below we only use the logger in development mode, however for both environments we assign a content_target_area.
server.configure(function(){ server.use(express.content_target_area("content")); }); server.configure('development', function(){ server.use(express.logger()); }); server.configure('production', function(){ });
For internal and arbitrary settings Client Express provides the set(key[, val]), enable(key) and disable(key) methods:
server.configure(function(){ server.set('views', '/views'); server.set('views'); // => "/absolute/path/to/views" server.enable('some feature'); // same as server.set('some feature', true); server.disable('some feature'); // same as server.set('some feature', false); server.enabled('some feature') // => false });
To alter the environment we can use the enable() function, for example:
server.enable('production');
Express supports the following settings out of the box:
Express utilizes the HTTP verbs to provide a meaningful, expressive routing API. For example we may want to render a user’s account for the path /user/12, this can be done by defining the route below. The values associated to the named placeholders are available as request.params.
server.get('/user/:id', function(request, response){ response.send('user ' + request.params.id); });
A route is simple a string which is compiled to a RegExp internally. For example when /user/:id is compiled, a simplified version of the regexp may look similar to:
\/user\/([^\/]+)\/?
Regular expression literals may also be passed for complex uses. Since capture groups with literal RegExp’s are anonymous we can access them directly request.params. So our first capture group would be request.params[0] and the second would follow as request.params[1].
server.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(request, response){ response.send(request.params); });
Below are some route examples, and the associated paths that they may consume:
"/user/:id" /user/12 "/users/:id?" /users/5 /users "/files/*" /files/jquery.js /files/javascripts/jquery.js "/file/*.*" /file/jquery.js /file/javascripts/jquery.js "/user/:id/:operation?" /user/1 /user/1/edit "/products.:format" /products.json /products.xml "/products.:format?" /products.json /products.xml /products "/user/:id.:format?" /user/12 /user/12.json
For example we can POST some json, and echo the json back using the bodyParser middleware which will parse json request bodies (as well as others), and place the result in request.body:
var server = require('express').createServer(); server.use(express.bodyParser()); server.post('/', function(request, response){ response.send(request.body); }); server.listen();
Typically we may use a “dumb” placeholder such as “/user/:id” which has no restrictions, however say for example we are limiting a user id to digits, we may use ‘/user/:id([0-9]+)’ which will not match unless the placeholder value contains only digits.
We may pass control to the next matching route, by calling the third argument, the next() function. When a match cannot be made, control is passed back to Connect, and middleware continue to be invoked in the order that they are added via use(). The same is true for several routes which have the same path defined, they will simply be executed in order until one does not call next() and decides to respond.
server.get('/users/:id?', function(request, response, next){ var id = request.params.id; if (id) { // do something } else { next(); } }); server.get('/users', function(request, response){ // do something else });
The server.all() method is useful for serverlying the same logic for all HTTP verbs in a single call. Below we use this to load a user from our fake database, and assign it to request.user.
var express = require('express') , server = express.createServer(); var users = [{ name: 'tj' }]; server.all('/user/:id/:op?', function(request, response, next){ request.user = users[request.params.id]; if (request.user) { next(); } else { next(new Error('cannot find user ' + request.params.id)); } }); server.get('/user/:id', function(request, response){ response.send('viewing ' + request.user.name); }); server.get('/user/:id/edit', function(request, response){ response.send('editing ' + request.user.name); }); server.put('/user/:id', function(request, response){ response.send('updating ' + request.user.name); }); server.get('*', function(request, response){ response.send('what???', 404); }); server.listen();
Routes may utilize route-specific middleware by passing one or more additional callbacks (or arrays) to the method. This feature is extremely useful for restricting access, loading data used by the route etc.
Typically async data retrieval might look similar to below, where we take the :id parameter, and attempt loading a user.
server.get('/user/:id', function(request, response, next){ loadUser(request.params.id, function(err, user){ if (err) return next(err); response.send('Viewing user ' + user.name); }); });
To keep things DRY and to increase readability we can serverly this logic within a middleware. As you can see below, abstracting this logic into middleware allows us to reuse it, and clean up our route at the same time.
function loadUser(request, response, next) { // You would fetch your user from the db var user = users[request.params.id]; if (user) { request.user = user; next(); } else { next(new Error('Failed to load user ' + request.params.id)); } } server.get('/user/:id', loadUser, function(request, response){ response.send('Viewing user ' + request.user.name); });
Multiple route middleware can be serverlied, and will be executed sequentially to serverly further logic such as restricting access to a user account. In the example below only the authenticated user may edit his/her account.
function andRestrictToSelf(request, response, next) { request.authenticatedUser.id == request.user.id ? next() : next(new Error('Unauthorized')); } server.get('/user/:id/edit', loadUser, andRestrictToSelf, function(request, response){ response.send('Editing user ' + request.user.name); });
Keeping in mind that middleware are simply functions, we can define function that returns the middleware in order to create a more expressive and flexible solution as shown below.
function andRestrictTo(role) { return function(request, response, next) { request.authenticatedUser.role == role ? next() : next(new Error('Unauthorized')); } } server.del('/user/:id', loadUser, andRestrictTo('admin'), function(request, response){ response.send('Deleted user ' + request.user.name); });
Commonly used “stacks” of middleware can be passed as an array (serverlied recursively), which can be mixed and matched to any degree.
var a = [middleware1, middleware2] , b = [middleware3, middleware4] , all = [a, b]; server.get('/foo', a, function(){}); server.get('/bar', a, function(){}); server.get('/', a, middleware3, middleware4, function(){}); server.get('/', a, b, function(){}); server.get('/', all, function(){});
For this example in full, view the route middleware example in the repository.
There are times when we may want to “skip” passed remaining route middleware, but continue matching subsequent routes. To do this we invoke next() with the string “route” next('route'). If no remaining routes match the request url then Express will respond with 404 Not Found.
We have seen server.get() a few times, however Express also exposes other familiar HTTP verbs in the same manor, such as server.post(), server.del(), etc.
A common example for POST usage, is when “submitting” a form. Below we simply set our form method to “post” in our html, and control will be given to the route we have defined below it.
<form method="post" action="/"> <input type="text" name="user[name]" /> <input type="text" name="user[email]" /> <input type="submit" value="Submit" /> </form>
Our route below will now have access to the request.body.user object which will contain the name and email properties when defined.
server.post('/', function(request, response){ console.log(request.body.user); response.redirect('back'); });
When using methods such as PUT with a form, we can utilize a hidden input named _method, which can be used to alter the HTTP method. This provides a great solution for forms. Below shows what the usage of PUT might look like:
<form method="post" action="/"> <input type="hidden" name="_method" value="put" /> <input type="text" name="user[name]" /> <input type="text" name="user[email]" /> <input type="submit" value="Submit" /> </form> server.put('/', function(){ console.log(request.body.user); response.redirect('back'); });
Express provides the server.error() method which receives exceptions thrown within a route, or passed to next(err). Below is an example which serves different pages based on our ad-hoc NotFound exception:
function NotFound(msg){ this.name = 'NotFound'; Error.call(this, msg); Error.captureStackTrace(this, arguments.callee); } NotFound.prototype.__proto__ = Error.prototype; server.get('/404', function(request, response){ throw new NotFound; }); server.get('/500', function(request, response){ throw new Error('keyboard cat!'); });
We can call server.error() several times as shown below. Here we check for an instanceof NotFound and show the 404 page, or we pass on to the next error handler.
Note that these handlers can be defined anywhere, as they will be placed below the route handlers on listen(). This allows for definition within configure() blocks so we can handle exceptions in different ways based on the environment.
server.error(function(err, req, res, next){ if (err instanceof NotFound) { response.render('404.jade'); } else { next(err); } });
Here we assume all errors as 500 for the simplicity of this demo, however you can choose whatever you like. For example when node performs filesystem syscalls, you may receive an error object with the error.code of ENOENT, meaning “no such file or directory”, we can utilize this in our error handling and display a page specific to this if desired.
server.error(function(err, req, res){ response.render('500.jade', { error: err }); });
Our servers could also utilize the Connect errorHandler middleware to report on exceptions. For example if we wish to output exceptions in “development” mode to stderr we can use:
server.use(express.errorHandler({ dumpExceptions: true }));
Also during development we may want fancy html pages to show exceptions that are passed or thrown, so we can set showStack to true:
server.use(express.errorHandler({ showStack: true, dumpExceptions: true }));
The errorHandler middleware also responds with json if Accept: serverlication/json is present, which is useful for developing servers that rely heavily on client-side JavaScript.
Route param pre-conditions can drastically improve the readability of your serverlication, through implicit loading of data, and validation of request urls. For example if you are constantly fetching common data for several routes, such as loading a user for /user/:id, we might typically do something like below:
server.get('/user/:userId', function(request, response, next){ User.get(request.params.userId, function(err, user){ if (err) return next(err); response.send('user ' + user.name); }); });
With preconditions our params can be mservered to callbacks which may perform validation, coercion, or even loading data from a database. Below we invoke server.param() with the parameter name we wish to map to some middleware, as you can see we receive the id argument which contains the placeholder value. Using this we load the user and perform error handling as usual, and simple call next() to pass control to the next precondition or route handler.
server.param('userId', function(request, response, next, id){ User.get(id, function(err, user){ if (err) return next(err); if (!user) return next(new Error('failed to find user')); request.user = user; next(); }); });
Doing so, as mentioned drastically improves our route readability, and allows us to easily share this logic throughout our serverlication:
server.get('/user/:userId', function(request, response){ response.send('user ' + request.user.name); });
View filenames take the form “<name>.<engine>”, where <engine> is the name of the module that will be required. For example the view layout.ejs will tell the view system to require(‘ejs’), the module being loaded must export the method exports.compile(str, options), and return a Function to comply with Express. To alter this behaviour server.register() can be used to map engines to file extensions, so that for example “foo.html” can be rendered by ejs.
Below is an example using Jade to render index.html, and since we do not use layout: false the rendered contents of index.jade will be passed as the body local variable in layout.jade.
server.get('/', function(request, response){ response.render('index.jade', { title: 'My Site' }); });
The new view engine setting allows us to specify our default template engine, so for example when using jade we could set:
server.set('view engine', 'jade');
Allowing us to render with:
response.render('index');
vs:
response.render('index.jade');
When view engine is set, extensions are entirely optional, however we can still mix and match template engines:
response.render('another-page.ejs');
The Express view system has built-in support for partials and collections, which are “mini” views representing a document fragment. For example rather than iterating in a view to display comments, we could use partial collection:
partial('comment', { collection: comments });
If no other options or local variables are desired, we can omit the object and simply pass our array, which is equivalent to above:
partial('comment', comments);
When using the partial collection support a few “magic” locals are provided for free:
Local variables passed (or generated) take precedence, however locals passed to the parent view are available in the child view as well. So for example if we were to render a blog post with partial(‘blog/post’, post) it would generate the post local, but the view calling this function had the local user, it would be available to the blog/post view as well.
For documentation on altering the object name view response.partial().
NOTE: be careful about when you use partial collections, as rendering an array with a length of 100 means we have to render 100 views. For simple collections you may inline the iteration instead of using partial collection support to decrease overhead.
View lookup is performed relative to the parent view, for example if we had a page view named views/user/list.jade, and within that view we did partial(‘edit’) it would attempt to load views/user/edit.jade, whereas partial(‘../messages’) would load views/messages.jade.
The view system also allows for index templates, allowing you to have a directory of the same name. For example within a route we may have response.render(‘users’) either views/users.jade, or views/users/index.jade.
When utilizing index views as shown above, we may reference views/users/index.jade from a view in the same directory by partial(‘users’), and the view system will try ../users/index, preventing us from needing to call partial(‘index’).
Below are a few template engines commonly used with Express:
Session support is nothing more then a global variable that stays a life as long as the server is a life. So once a user has refreshed a page manually the session is gone.
The request.session property will be accessible to all routes and subsequent middleware. Properties on request.session are automatically saved on a response, so for example if we wish to shopping cart data:
server.post('/add-to-cart', function(request, response){ // Perhaps we posted several items with a form var items = request.body.items; request.session.items = items; response.redirect('back'); }); server.get('/add-to-cart', function(request, response){ // When redirected back to GET /add-to-cart // we could check request.session.items && request.session.items.length // to print out a message if (request.session.items && request.session.items.length) { request.flash('info', 'You have %s items in your cart', request.session.items.length); } response.render('shopping-cart'); });
Get the case-insensitive request header key, with optional defaultValue:
request.header('Host'); request.header('host'); request.header('Accept', '*/*');
The Referrer and Referer header fields are special-cased, either will work:
// sent Referrer: http://google.com request.header('Referer'); // => "http://google.com" request.header('Referrer'); // => "http://google.com"
Check if the Accept header is present, and includes the given type.
When the Accept header is not present true is returned. Otherwise the given type is matched by an exact match, and then subtypes. You may pass the subtype such as “html” which is then converted internally to “text/html” using the mime lookup table.
// Accept: text/html request.accepts('html'); // => true // Accept: text/*; serverlication/json request.accepts('html'); request.accepts('text/html'); request.accepts('text/plain'); request.accepts('serverlication/json'); // => true request.accepts('image/png'); request.accepts('png'); // => false
Check if the incoming request contains the Content-Type header field, and it contains the give mime type.
// With Content-Type: text/html; charset=utf-8 request.is('html'); request.is('text/html'); // => true // When Content-Type is serverlication/json request.is('json'); request.is('serverlication/json'); // => true request.is('html'); // => false
Ad-hoc callbacks can also be registered with Express, to perform assertions again the request, for example if we need an expressive way to check if our incoming request is an image, we can register “an image” callback:
server.is('an image', function(req){ return 0 == request.headers['content-type'].indexOf('image'); });
Now within our route callbacks, we can use to to assert content types such as “image/jpeg”, “image/png”, etc.
server.post('/image/upload', function(request, response, next){ if (request.is('an image')) { // do something } else { next(); } });
Keep in mind this method is not limited to checking Content-Type, you can perform any request assertion you wish.
Wildcard matches can also be made, simplifying our example above for “an image”, by asserting the subtype only:
request.is('image/*');
We may also assert the type as shown below, which would return true for “serverlication/json”, and “text/json”.
request.is('*/json');
Return the value of param name when present or default.
To utilize urlencoded request bodies, request.body should be an object. This can be done by using the _express.bodyParser middleware.
Get field’s param value, defaulting to ‘’ when the param or field is not present.
request.get('content-disposition', 'filename'); // => "something.png" request.get('Content-Type', 'boundary'); // => "--foo-bar-baz"
Queue flash msg of the given type.
request.flash('info', 'email sent'); request.flash('error', 'email delivery failed'); request.flash('info', 'email re-sent'); // => 2 request.flash('info'); // => ['email sent', 'email re-sent'] request.flash('info'); // => [] request.flash(); // => { error: ['email delivery failed'], info: [] }
Flash notification message may also utilize formatters, by default only the %s string formatter is available:
request.flash('info', 'email delivery to _%s_ from _%s_ failed.', toUser, fromUser);
Also aliased as request.xhr, this getter checks the X-Requested-With header to see if it was issued by an XMLHttpRequest:
request.xhr request.isXMLHttpRequest
Get or set the response header key.
response.header('Content-Length'); // => undefined response.header('Content-Length', 123); // => 123 response.header('Content-Length'); // => 123
Sets the charset for subsequent Content-Type header fields. For example response.send() and response.render() default to “utf8”, so we may explicitly set the charset before rendering a template:
response.charset = 'ISO-8859-1'; response.render('users');
or before responding with response.send():
response.charset = 'ISO-8859-1'; response.send(str);
or with node’s response.end():
response.charset = 'ISO-8859-1'; response.header('Content-Type', 'text/plain'); response.end(str);
Sets the Content-Type response header to the given type.
var filename = 'path/to/image.png'; response.contentType(filename); // Content-Type is now "image/png"
A literal Content-Type works as well:
response.contentType('serverlication/json');
Or simply the extension without leading .:
response.contentType('json');
Sets the Content-Disposition response header to “attachment”, with optional filename.
response.attachment('path/to/my/image.png');
Used by response.download() to transfer an arbitrary file.
response.sendfile('path/to/my.file');
This method accepts an optional callback which is called when an error occurs, or when the transfer is complete. By default failures call next(err), however when a callback is supplied you must do this explicitly, or act on the error.
response.sendfile(path, function(err){ if (err) { next(err); } else { console.log('transferred %s', path); } });
Options may also be passed to the internal fs.createReadStream() call, for example altering the bufferSize:
response.sendfile(path, { bufferSize: 1024 }, function(err){ // handle });
Transfer the given file as an attachment with optional alternative filename.
response.download('path/to/image.png'); response.download('path/to/image.png', 'foo.png');
This is equivalent to:
response.attachment(file); response.sendfile(file);
An optional callback may be supplied as either the second or third argument, which is passed to response.sendfile(). Within this callback you may still respond, as the header has not been sent.
response.download(path, 'expenses.doc', function(err){ // handle });
An optional second callback, callback2 may be given to allow you to act on connection related errors, however you should not attempt to respond.
response.download(path, function(err){ // error or finished }, function(err){ // connection related error });
The response.send() method is a high level response utility allowing you to pass objects to respond with json, strings for html, Buffer instances, or numbers representing the status code. The following are all valid uses:
response.send(); // 204 response.send(new Buffer('wahoo')); response.send({ some: 'json' }); response.send('<p>some html</p>'); response.send('Sorry, cant find that', 404); response.send('text', { 'Content-Type': 'text/plain' }, 201); response.send(404);
By default the Content-Type response header is set, however if explicitly assigned through response.send() or previously with response.header() or response.contentType() it will not be set again.
Note that this method end()s the response, so you will want to use node’s response.write() for multiple writes or streaming.
Redirect to the given url with a default response status of 302.
response.redirect('/', 301); response.redirect('/account'); response.redirect('http://google.com'); response.redirect('home'); response.redirect('back');
Express supports “redirect mservering”, which by default provides home, and back. The back map checks the Referrer and Referer headers, while home utilizes the “home” setting and defaults to “/”.
Sets the given cookie name to val, with options httpOnly, secure, expires etc.
// "Remember me" for 15 minutes response.cookie('rememberme', 'yes', { expires: new Date(Date.now() + 900000), httpOnly: true });
The maxAge property may be used to set expires relative to Date.now() in milliseconds, so our example above can now become:
response.cookie('rememberme', 'yes', { maxAge: 900000 });
To parse incoming Cookie headers, use the cookieParser middleware, which provides the request.cookies object:
server.use(express.cookieParser()); server.get('/', function(request, response){ // use request.cookies.rememberme });
Clear cookie name by setting “expires” far in the past.
response.clearCookie('rememberme');
Render view with the given options and optional callback fn. When a callback function is given a response will not be made automatically, however otherwise a response of 200 and text/html is given.
The options passed are the local variables as well, for example if we want to expose “user” to the view, and prevent a local we do so within the same object:
var user = { name: 'tj' }; response.render('index', { layout: false, user: user });
Render view partial with the given options. This method is always available to the view as a local variable.
as Variable name for each collection or object value, defaults to the view name.
collection Array of objects, the name is derived from the view name itself. For example video.html will have a object video available to it.
The following are equivalent, and the name of collection value when passed to the partial will be movie as derived from the name.
partial('theatre/movie.jade', { collection: movies }); partial('theatre/movie.jade', movies); partial('movie.jade', { collection: movies }); partial('movie.jade', movies); partial('movie', movies); // In view: movie.director
To change the local from movie to video we can use the “as” option:
partial('movie', { collection: movies, as: 'video' }); // In view: video.director
Also we can make our movie the value of this within our view so that instead of movie.director we could use this.director.
partial('movie', { collection: movies, as: this }); // In view: this.director
Another alternative is to “expand” the properties of the collection item into pseudo globals (local variables) by using as: global, which again is syntactic sugar:
partial('movie', { collection: movies, as: global }); // In view: director
This same logic serverlies to a single partial object usage:
partial('movie', { object: movie, as: this }); // In view: this.director partial('movie', { object: movie, as: global }); // In view: director partial('movie', { object: movie, as: 'video' }); // In view: video.director partial('movie', { object: movie }); // In view: movie.director
When a non-collection (does not have .length) is passed as the second argument, it is assumed to be the object, after which the object’s local variable name is derived from the view name:
var movie = new Movie('Nightmare Before Christmas', 'Tim Burton') partial('movie', movie) // => In view: movie.director
The exception of this, is when a “plain” object, aka “{}” or “new Object” is passed, which is considered an object with local variable. For example some may expect a “movie” local with the following, however since it is a plain object “director” and “title” are simply locals:
var movie = { title: 'Nightmare Before Christmas', director: 'Tim Burton' }; partial('movie', movie)
For cases like this where passing a plain object is desired, simply assign it to a key, or use the object key which will use the filename-derived variable name. The examples below are equivalent:
partial('movie', { locals: { movie: movie }}) partial('movie', { movie: movie }) partial('movie', { object: movie })
This exact API can be utilized from within a route, to respond with a fragment via Ajax or WebSockets, for example we can render a collection of users directly from a route:
server.get('/users', function(request, response){ if (request.xhr) { // respond with the each user in the collection // passed to the "user" view response.partial('user', users); } else { // respond with layout, and users page // which internally does partial('user', users) // along with other UI response.render('users', { users: users }); } });
Get or set the given local variable name. The locals built up for a response are serverlied to those given to the view rendering methods such as response.render().
server.all('/movie/:id', function(request, response, next){ Movie.get(request.params.id, function(err, movie){ // Assigns response.locals.movie = movie response.local('movie', movie); }); }); server.get('/movie/:id', function(request, response){ // movie is already a local, however we // can pass more if we wish response.render('movie', { displayReviews: true }); });
Assign several locals with the given obj. The following are equivalent:
response.local('foo', bar); response.local('bar', baz); response.locals({ foo: bar, bar, baz });
serverly an serverlication level setting name to val, or get the value of name when val is not present:
server.set('views', '/views'); server.set('views'); // => ...path...
Alternatively you may simply access the settings via server.settings:
server.settings.views // => ...path...
Enable the given setting name:
server.enable('some arbitrary setting'); server.set('some arbitrary setting'); // => true server.enabled('some arbitrary setting'); // => true
Check if setting name is enabled:
server.enabled('view cache'); // => false server.enable('view cache'); server.enabled('view cache'); // => true
Disable the given setting name:
server.disable('some setting'); server.set('some setting'); // => false server.disabled('some setting'); // => false
Check if setting name is disabled:
server.enable('view cache'); server.disabled('view cache'); // => false server.disable('view cache'); server.disabled('view cache'); // => true
Define a callback function for the given env (or all environments) with callback function:
server.configure(function(){ // executed for each env }); server.configure('development', function(){ // executed for 'development' only });
For use with response.redirect() we can map redirects at the serverlication level as shown below:
server.redirect('google', 'http://google.com');
Now in a route we may call:
response.redirect(‘google’);
We may also map dynamic redirects:
server.redirect('comments', function(request, response){ return '/post/' + request.params.id + '/comments'; });
So now we may do the following, and the redirect will dynamically adjust to the context of the request. If we called this route with GET /post/12 our redirect Location would be /post/12/comments.
server.get('/post/:id', function(request, response){ response.redirect('comments'); });
When mounted, response.redirect() will respect the mount-point. For example if a blog server is mounted at /blog, the following will redirect to /blog/posts:
response.redirect('/posts');
Adds an error handler function which will receive the exception as the first parameter as shown below. Note that we may set several error handlers by making several calls to this method, however the handler should call next(err) if it does not wish to deal with the exception:
server.error(function(err, req, res, next){ response.send(err.message, 500); });
Registers static view helpers.
server.helpers({ name: function(first, last){ return first + ', ' + last } , firstName: 'tj' , lastName: 'holowaychuk' });
Our view could now utilize the firstName and lastName variables, as well as the name() function exposed.
<%= name(firstName, lastName) %>
Express also provides a few locals by default:
- `settings` the server's settings object - `filename` the view's filename - `layout(path)` specify the layout from within a view
This method is aliased as server.locals().
Registers dynamic view helpers. Dynamic view helpers are simply functions which accept req, res, and are evaluated against the Server instance before a view is rendered. The return value of this function becomes the local variable it is associated with.
server.dynamicHelpers({ session: function(request, response){ return request.session; } });
All views would now have session available so that session data can be accessed via session.name etc:
<%= session.name %>
The server.lookup http methods returns an array of callback functions associated with the given path.
Suppose we define the following routes:
server.get('/user/:id', function(){}); server.put('/user/:id', function(){}); server.get('/user/:id/:op?', function(){});
We can utilize this lookup functionality to check which routes have been defined, which can be extremely useful for higher level frameworks built on Express.
server.lookup.get('/user/:id'); // => [Function] server.lookup.get('/user/:id/:op?'); // => [Function] server.lookup.put('/user/:id'); // => [Function] server.lookup.all('/user/:id'); // => [Function, Function] server.lookup.all('/hey'); // => []
To alias server.lookup.VERB(), we can simply invoke server.VERB() without a callback, as a shortcut, for example the following are equivalent:
server.lookup.get('/user'); server.get('/user');
Each function returned has the following properties:
var fn = server.get('/user/:id/:op?')[0]; fn.regexp // => /^\/user\/(?:([^\/]+?))(?:\/([^\/]+?))?\/?$/i fn.keys // => ['id', 'op'] fn.path // => '/user/:id/:op?' fn.method // => 'GET'
The server.match http methods return an array of callback functions which match the given url, which may include a query string etc. This is useful when you want reflect on which routes have the opportunity to respond.
Suppose we define the following routes:
server.get('/user/:id', function(){}); server.put('/user/:id', function(){}); server.get('/user/:id/:op?', function(){});
Our match against GET will return two functions, since the :op in our second route is optional.
server.match.get('/user/1'); // => [Function, Function]
This second call returns only the callback for /user/:id/:op?.
server.match.get('/user/23/edit'); // => [Function]
We can also use all() to disregard the http method:
server.match.all('/user/20'); // => [Function, Function, Function]
Each function matched has the following properties:
var fn = server.match.get('/user/23/edit')[0]; fn.keys // => ['id', 'op'] fn.params // => { id: '23', op: 'edit' } fn.method // => 'GET'
Assign a callback fn which is called when this Server is passed to Server#use().
var server = express.createServer(), blog = express.createServer(); blog.mounted(function(parent){ // parent is server // "this" is blog }); server.use(blog);
Register the given template engine exports as ext. For example we may wish to map “.html” files to jade:
server.register('.html', require('jade'));
This is also useful for libraries that may not match extensions correctly. For example my haml.js library is installed from npm as “hamljs” so instead of layout.hamljs, we can register the engine as “.haml”:
server.register('.haml', require('haml-js'));
For engines that do not comply with the Express specification, we can also wrap their api this way. Below we map .md to render markdown files, rendering the html once since it will not change on subsequent calls, and support local substitution in the form of “{name}”.
server.register('.md', { compile: function(str, options){ var html = md.toHTML(str); return function(locals){ return html.replace(/\{([^}]+)\}/g, function(_, name){ return locals[name]; }); }; } });
Bind the server to the following events: onClick, onSubmit and onPopState which means that it will intercept clicking of links and submitting of forms and also the back and forward actions. server.listen() also triggers the loading of the configuration functions after the DOM is loaded.
server.listen();