GUIDE()

NAME
guide

  Installation
curl:

    $ curl -# http://expressjs.com/install.sh | sh

npm:

    $ npm install express

git clone, first update the submodules:

    $ git submodule update --init
    $ make install
    $ make install-support

  Creating An Application
The express.Server now inherits from http.Server, however follows the same idiom by providing express.createServer() as shown below. This means that you can utilize Express server's transparently with other libraries.

    var app = require('express').createServer();
    app.get('/', function(req, res){
        res.send('hello world');
    });
    app.listen(3000);

  Configuration
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 prior to the environment specific callback.

In the example below we only dumpExceptions, and respond with exception stack traces in development mode, however for both environments we utilize methodOverride and bodyDecoder. Note the use of app.router, which can (optionally) be used to mount the application routes, otherwise the first call to app.{get,put,del,post}() will mount the routes.

    app.configure(function(){
        app.use(express.methodOverride());
        app.use(express.bodyDecoder());
        app.use(app.router);
        app.use(express.staticProvider(__dirname + '/public'));
    });
    app.configure('development', function(){
        app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
    });
    app.configure('production', function(){
        app.use(express.errorHandler());
    });

For internal and arbitrary settings Express provides the set(key[, val]), enable(key), disable(key) methods:

    app.configure(function(){
        app.set('views', __dirname + '/views');
        app.set('views');
        // => "... views directory ..."
        app.enable('some feature');
        // same as app.set('some feature', true);
        app.disable('some feature');
        // same as app.set('some feature', false);
    });

To alter the environment we can set the NODE_ENV environment variable, for example:

    $ NODE_ENV=production node app.js

This is very important, as many caching mechanisms are only enabled when in production.

  Settings
Express supports the following settings out of the box:

•   env Application environment set internally, use app.set('env') on Server#listen()

•   home Application base path used for res.redirect() and transparently handling mounted apps.

•   views Root views directory defaulting to CWD/views

•   view engine Default view engine name for views rendered without extensions

•   view options An object specifying global view options

•   partials Root view partials directory defaulting to views/partials.

•   stream threshold Bytesize indicating when a file should be streamed for res.sendfile() using fs.ReadStream() and sys.pump().

  Routing
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 req.params.

    app.get('/user/:id', function(req, res){
        res.send('user ' + req.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 req.params.

    app.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(req, res){
        res.send(req.params);
    });

Curl requests against the previously defined route:

       $ curl http://dev:3000/user
       [null,null]
       $ curl http://dev:3000/users
       [null,null]
       $ curl http://dev:3000/users/1
       ["1",null]
       $ curl http://dev:3000/users/1..15
       ["1","15"]

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/*.*"
     /files/jquery.js
     /files/javascripts/jquery.js
     "/user/:id/:operation?"
     /user/1
     /user/1/edit
     "/products.:format"
     /products.json
     /products.xml
     "/products.:format?"
     /products.json
     /products.xml
     /products

  Passing Route Control
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. 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().

    app.get('/users/:id?', function(req, res, next){
        var id = req.params.id;
        if (id) {
            // do something
        } else {
            next();
        }
    });
    app.get('/users', function(req, res){
        // do something else
    });

  Middleware
Middleware via Connect http://github.com/senchalabs/connect can be passed to express.createServer() as you would with a regular Connect server. For example:

      var express = require('express');
    var app = express.createServer(
        express.logger(),
        express.bodyDecoder()
      );

Alternatively we can use() them which is useful when adding middleware within configure() blocks:

    app.use(express.logger({ format: ':method :uri' }));

Typically with connect middleware you would require('connect') like so:

    var connect = require('connect');
    app.use(connect.logger());

This is somewhat annoying, so express re-exports these middleware properties, however they are identical:

    app.use(express.logger());

  Route Middleware
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.

    app.get('/user/:id', function(req, res, next){
        loadUser(req.params.id, function(err, user){
            if (err) return next(err);
            res.send('Viewing user ' + user.name);
        });
    });

To keep things DRY and to increase readability we can apply 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(req, res, next) {
        // You would fetch your user from the db
        var user = users[req.params.id];
        if (user) {
            req.user = user;
            next();
        } else {
            next(new Error('Failed to load user ' + req.params.id));
        }
    }
    app.get('/user/:id', loadUser, function(req, res){
        res.send('Viewing user ' + req.user.name);
    });

Multiple route middleware can be applied, and will be executed sequentially to apply 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(req, res, next) {
        req.authenticatedUser.id == req.user.id
            ? next()
            : next(new Error('Unauthorized'));
    }
    app.get('/user/:id/edit', loadUser, andRestrictToSelf, function(req, res){
        res.send('Editing user ' + req.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(req, res, next) {
          req.authenticatedUser.role == role
              ? next()
              : next(new Error('Unauthorized'));
        }
    }
    app.del('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
        res.send('Deleted user ' + req.user.name);
    });

Commonly used "stacks" of middleware can be passed as an array (applied recursively), which can be mixed and matched to any degree.

    var a = [middleware1, middleware2]
      , b = [middleware3, middleware4]
      , all = [a, b];
    app.get('/foo', a, function(){});
    app.get('/bar', a, function(){});
    app.get('/', a, middleware3, middleware4, function(){});
    app.get('/', a, b, function(){});
    app.get('/', all, function(){});

For this example in full, view the route middleware example http://github.com/visionmedia/express/blob/master/examples/route-middleware/app.js in the repository.

  HTTP Methods
We have seen app.get() a few times, however Express also exposes other familiar HTTP verbs in the same manor, such as app.post(), app.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>

By default Express does not know what to do with this request body, so we should add the bodyDecoder middleware, which will parse application/x-www-form-urlencoded request bodies and place the variables in req.body. We can do this by "using" the middleware as shown below:

    app.use(express.bodyDecoder());

Our route below will now have access to the req.body.user object which will contain the name and email properties when defined.

    app.post('/', function(req, res){
        console.log(req.body.user);
        res.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. To do so we first need the methodOverride middleware, which should be placed below bodyDecoder so that it can utilize it's req.body containing the form values.

    app.use(express.bodyDecoder());
    app.use(express.methodOverride());

The reason that these are not always defaults, is simply because these are not required for Express to be fully functional. Depending on the needs of your application, you may not need these at all, your methods such as PUT and DELETE can still be accessed by clients which can use them directly, although methodOverride 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>
    app.put('/', function(){
        console.log(req.body.user);
        res.redirect('back');
    });

  Error Handling
Express provides the app.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);
    }
    sys.inherits(NotFound, Error);
    app.get('/404', function(req, res){
        throw new NotFound;
    });
    app.get('/500', function(req, res){
        throw new Error('keyboard cat!');
    });

We can call app.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.

    app.error(function(err, req, res, next){
        if (err instanceof NotFound) {
            res.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

    app.error(function(err, req, res){
        res.render('500.jade', {
           locals: {
               error: err
           }
        });
    });

Our apps 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:

    app.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:

    app.use(express.errorHandler({ showStack: true, dumpExceptions: true }));

The errorHandler middleware also responds with json if Accept: application/json is present, which is useful for developing apps that rely heavily on client-side JavaScript.

  View Rendering
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.render(str, options) to comply with Express, however app.register() can be used to map engines to file extensions, so that for example "foo.html" can be rendered by jade.

Below is an example using Haml.js http://github.com/visionmedia/haml.js to render index.html, and since we do not use layout: false the rendered contents of index.html will be passed as the body local variable in layout.haml.

    app.get('/', function(req, res){
        res.render('index.haml', {
            locals: { title: 'My Site' }
        });
    });

The new view engine setting allows us to specify our default template engine, so for example when using Jade http://github.com/visionmedia/jade we could set:

    app.set('view engine', 'jade');

Allowing us to render with:

    res.render('index');

vs:

    res.render('index.jade');

When view engine is set, extensions are entirely optional, however we can still mix and match template engines:

    res.render('another-page.ejs');

Express also provides the view options setting, which is applied each time a view is rendered, so for example if you rarely use layouts you may set:

    app.set('view options', {
        layout: false
    });

Which can then be overridden within the res.render() call if need be:

    res.render('myview.ejs', { layout: true });

When an alternate layout is required, we may also specify a path. For example if we have view engine set to jade and a file named ./views/mylayout.jade we can simply pass:

    res.render('page', { layout: 'mylayout' });

Otherwise we must specify the extension:

    res.render('page', { layout: 'mylayout.jade' });

These paths may also be absolute:

    res.render('page', { layout: __dirname + '/../../mylayout.jade' });

A good example of this is specifying custom ejs opening and closing tags:

    app.set('view options', {
        open: '{{',
        close: '}}'
    });

  View Partials
The Express view system has built-in support for partials and collections, which are sort of "mini" views representing a document fragment. For example rather than iterating in a view to display comments, we would use a partial with collection support:

    partial('comment.haml', { collection: comments });

To make things even less verbose we can assume the extension as .haml when omitted, however if we wished we could use an ejs partial, within a haml view for example.

    partial('comment', { collection: comments });

And once again even further, when rendering a collection we can simply pass an array, if no other options are desired:

    partial('comment', comments);

When using the partial collection support a few "magic" variables are provided for free:

•   firstInCollection True if this is the first object

•   indexInCollection Index of the object in the collection

•   lastInCollection True if this is the last object

•   collectionLength Length of the collection

For documentation on altering the object name view res.partial() http://expressjs.com/guide.html#res-partial-view-options-.

  Template Engines
Below are a few template engines commonly used with Express:

•   Jade http://jade-lang.com haml.js successor

•   Haml http://github.com/visionmedia/haml.js pythonic indented templates

•   EJS http://github.com/visionmedia/ejs Embedded JavaScript

•   CoffeeKup http://github.com/mauricemach/coffeekup CoffeeScript based templating

  Session Support
Sessions support can be added by using Connect's session middleware. To do so we also need the cookieDecoder middleware place above it, which will parse and populate cookie data to req.cookies.

    app.use(express.cookieDecoder());
    app.use(express.session());

By default the session middleware uses the memory store bundled with Connect, however many implementations exist. For example connect-redis http://github.com/visionmedia/connect-redis supplies a Redis http://code.google.com/p/redis/ session store and can be used as shown below:

    var RedisStore = require('connect-redis');
    app.use(express.cookieDecoder());
    app.use(express.session({ store: new RedisStore }));

Now the req.session and req.sessionStore properties will be accessible to all routes and subsequent middleware. Properties on req.session are automatically saved on a response, so for example if we wish to shopping cart data:

    var RedisStore = require('connect-redis');
    app.use(express.bodyDecoder());
    app.use(express.cookieDecoder());
    app.use(express.session({ store: new RedisStore }));
    app.post('/add-to-cart', function(req, res){
      // Perhaps we posted several items with a form
      // (use the bodyDecoder() middleware for this)
      var items = req.body.items;
      req.session.items = items;
      res.redirect('back');
    });
    app.get('/add-to-cart', function(req, res){
      // When redirected back to GET /add-to-cart
      // we could check req.session.items && req.session.items.length
      // to print out a message
      if (req.session.items && req.session.items.length) {
        req.flash('info', 'You have %s items in your cart', req.session.items.length);
      }
      res.render('shopping-cart');
    });

The req.session object also has methods such as Session#touch(), Session#destroy(), Session#regenerate() among others to maintain and manipulate sessions. For more information view the Connect Session http://senchalabs.github.com/connect/session.html documentation.

  Migration Guide
Pre-beta Express developers may reference the Migration Guide migrate.html to get up to speed on how to upgrade your application.

  req.header(key[, defaultValue])
Get the case-insensitive request header key, with optional defaultValue:

    req.header('Host');
    req.header('host');
    req.header('Accept', '*/*');

  req.accepts(type)
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
    req.accepts('html');
    // => true
    // Accept: text/*; application/json
    req.accepts('html');
    req.accepts('text/html');
    req.accepts('text/plain');
    req.accepts('application/json');
    // => true
    req.accepts('image/png');
    req.accepts('png');
    // => false

  req.is(type)
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
       req.is('html');
       req.is('text/html');
       // => true
       // When Content-Type is application/json
       req.is('json');
       req.is('application/json');
       // => true
       req.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:

        app.is('an image', function(req){
          return 0 == req.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.

       app.post('/image/upload', function(req, res, next){
         if (req.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:

    req.is('image/*');

We may also assert the type as shown below, which would return true for "application/json", and "text/json".

    req.is('*/json');

  req.param(name)
Return the value of param name when present.

•   Checks route placeholders (req.params), ex: /user/:id

•   Checks query string params (req.query), ex: ?id=12

•   Checks urlencoded body params (req.body), ex: id=12

To utilize urlencoded request bodies, req.body should be an object. This can be done by using the express.bodyDecoder middleware.

  req.flash(type[, msg])
Queue flash msg of the given type.

    req.flash('info', 'email sent');
    req.flash('error', 'email delivery failed');
    req.flash('info', 'email re-sent');
    // => 2
    req.flash('info');
    // => ['email sent', 'email re-sent']
    req.flash('info');
    // => []
    req.flash();
    // => { error: ['email delivery failed'], info: [] }

Flash notification message may also utilize formatters, by default only the %s string formatter is available:

    req.flash('info', 'email delivery to _%s_ from _%s_ failed.', toUser, fromUser);

  req.isXMLHttpRequest
Also aliased as req.xhr, this getter checks the X-Requested-With header to see if it was issued by an XMLHttpRequest:

    req.xhr
    req.isXMLHttpRequest

  res.header(key[, val])
Get or set the response header key.

    res.header('Content-Length');
    // => undefined
    res.header('Content-Length', 123);
    // => 123
    res.header('Content-Length');
    // => 123

  res.contentType(type)
Sets the Content-Type response header to the given type.

      var filename = 'path/to/image.png';
      res.contentType(filename);
      // res.headers['Content-Type'] is now "image/png"

  res.attachment([filename])
Sets the Content-Disposition response header to "attachment", with optional filename.

      res.attachment('path/to/my/image.png');

  res.sendfile(path)
Used by res.download() to transfer an arbitrary file.

    res.sendfile('path/to/my.file');

This method accepts a callback which when given will be called on an exception, as well as when the transfer has completed. When a callback is not given, and the file has not been streamed, next(err) will be called on an exception.

    res.sendfile(path, function(err, path){
      if (err) {
        // handle the error
      } else {
        console.log('transferred %s', path);
      }
    });

When the filesize exceeds the stream threshold (defaulting to 32k), the file will be streamed using fs.ReadStream and sys.pump().

  res.download(file[, filename])
Transfer the given file as an attachment with optional alternative filename.

    res.download('path/to/image.png');
    res.download('path/to/image.png', 'foo.png');

This is equivalent to:

    res.attachment(file);
    res.sendfile(file);

  res.send(body|status[, headers|status[, status]])
The res.send() method is a high level response utility allowing you to pass objects to respond with json, strings for html, arbitrary _Buffer_s or numbers for status code based responses. The following are all valid uses:

     res.send(); // 204
     res.send(new Buffer('wahoo'));
     res.send({ some: 'json' });
     res.send('<p>some html</p>');
     res.send('Sorry, cant find that', 404);
     res.send('text', { 'Content-Type': 'text/plain' }, 201);
     res.send(404);

By default the Content-Type response header is set, however if explicitly assigned through res.send() or previously with res.header() or res.contentType() it will not be set again.

  res.redirect(url[, status])
Redirect to the given url with a default response status of 302.

    res.redirect('/', 301);
    res.redirect('/account');
    res.redirect('http://google.com');
    res.redirect('home');
    res.redirect('back');

Express supports "redirect mapping", 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 "/".

  res.cookie(name, val[, options])
Sets the given cookie name to val, with options such as "httpOnly: true", "expires", "secure" etc.

    // "Remember me" for 15 minutes
    res.cookie('rememberme', 'yes', { expires: new Date(Date.now() + 900000), httpOnly: true });

To parse incoming Cookie headers, use the cookieDecoder middleware, which provides the req.cookies object:

    app.use(express.cookieDecoder());
    app.get('/', function(req, res){
        // use req.cookies.rememberme
    });

  res.clearCookie(name)
Clear cookie name by setting "expires" far in the past.

    res.clearCookie('rememberme');

  res.render(view[, options[, fn]])
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.

Most engines accept one or more of the following options, both haml http://github.com/visionmedia/haml.js and jade http://github.com/visionmedia/jade accept all:

•   scope Template evaluation context (value of this)

•   locals Object containing local variables

•   debug Output debugging information

•   status Response status code, defaults to 200

•   headers Response headers object

  res.partial(view[, options])
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 value, defaults to the view name.

•   as: 'something' will add the something local variable

•   as: this will use the collection value as the template context

•   as: global will merge the collection value's properties with locals

•   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 "explode" the properties of the collection item into pseudo globals (local variables) by using as: global, which again is syntactic sugar:

    partials('movie', { collection: movies, as: global });
    // In view: director

  app.set(name[, val])
Apply an application level setting name to val, or get the value of name when val is not present:

    app.set('views', __dirname + '/views');
    app.set('views');
    // => ...path...

  app.enable(name)
Enable the given setting name:

    app.enable('some arbitrary setting');
    app.set('some arbitrary setting');
    // => true

  app.disable(name)
Disable the given setting name:

    app.disable('some setting');
    app.set('some setting');
    // => false

  app.configure(env|function[, function])
Define a callback function for the given env (or all environments) with callback function:

    app.configure(function(){
        // executed for each env
    });
    app.configure('development', function(){
        // executed for 'development' only
    });

  app.redirect(name, val)
For use with res.redirect() we can map redirects at the application level as shown below:

    app.redirect('google', 'http://google.com');

Now in a route we may call:

res.redirect('google');

We may also map dynamic redirects:

    app.redirect('comments', function(req, res){
        return '/post/' + req.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.

    app.get('/post/:id', function(req, res){
        res.redirect('comments');
    });

  app.error(function)
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:

    app.error(function(err, req, res, next){
        res.send(err.message, 500);
    });

  app.helpers(obj)
Registers static view helpers.

    app.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) %>

  app.dynamicHelpers(obj)
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.

    app.dynamicHelpers({
        session: function(req, res){
            return req.session;
        }
    });

All views would now have session available so that session data can be accessed via session.name etc:

    <%= session.name %>

  app.mounted(fn)
Assign a callback fn which is called when this Server is passed to Server#use().

    var app = express.createServer(),
        blog = express.createServer();
    blog.mounted(function(parent){
        // parent is app
        // "this" is blog
    });
    app.use(blog);

  app.register(ext, exports)
Register the given template engine exports as ext. For example we may wish to map ".html" files to jade:

     app.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":

     app.register('.haml', require('haml-js'));

For engines that do not comply with the Express specification, we can also wrap their api this way.

     app.register('.foo', {
         render: function(str, options) {
             // perhaps their api is
             // return foo.toHTML(str, options);
         }
     });

  app.listen([port[, host]])
Bind the app server to the given port, which defaults to 3000. When host is omitted all connections will be accepted via INADDR_ANY.

    app.listen();
    app.listen(3000);
    app.listen(3000, 'n.n.n.n');

The port argument may also be a string representing the path to a unix domain socket:

    app.listen('/tmp/express.sock');

Then try it out:

    $ telnet /tmp/express.sock
    GET / HTTP/1.1
    HTTP/1.1 200 OK
    Content-Type: text/plain
    Content-Length: 11
    Hello World