First steps

Request and response object inherit from the Node http module's IncomingMessage and ServerResponse respectively.

lib/request.js:

var req = exports = module.exports = {
  __proto__: http.IncomingMessage.prototype
};

lib/response.js:

var req = exports = module.exports = {
  __proto__: http.ServerResponse.prototype
};

This inheritance allows you to call Node functions from Express apps. For example:

app.get('/', function(request, response) {
  response.write('Hello World'); // Node API
  response.end(); // Node API
  // OR //
  response.send('Hello World'); // Express API
});

response.send automatically serialises objects and arrays to JSON and includes appropriate headers.  If response.send a string, express will automatically respond as type 'text/html'. response.json works the same as .send for objects and arrays.

Middleware

Middleware are functions added to the stack that have access to the request and response objects and are executed sequentially.

A request that comes in is passed through each of the middleware sequentially, before reaching the route which handles the response.

Middleware is added to the stack using:

app.use(function(req, res, next){
  ...
  next(); // next must be called to pass processing to the next middleware in the stack
});

Final response can either be processed from middleware or from a route.  Once response sent, middleware processing stops and response is sent.

Custom Middleware

Response object is an EventEmitter. Can listen for its events to know when response is finished.

module.exports = function (req, res. next) {
  var start = +new Date(); // + converts date to milliseconds since 1970
  var stream = process.stdout // standard output is a writeable stream accessible via process.stdout
  var url = req.url;
  var method = req.method;

  response.on('finish', function() {
    var duration = +new Date() - start;
    var message = method ' to ' + url + ' took ' duration;
    stream.write(message);
  }); // this callback runs asynchronously

  next();

};

URLs

Query string parameters allow for uses such as limiting the number of results returned.

Dynamic routes are placeholders that can be used to name arguments as part of the URL path.  Dynamic route preceded by colon '/route/:dynamic'.

app.param function maps placeholders to callback functions.  Its useful for running pre-conditions on dynamic routes.

For example, every /route/:name' dynamic route:

app.param('name', function(req, res, next) {
  // manipulate all :name dynamic routes
});

Post and delete requests

Routes can take multiple handlers as arguments and will run them sequentially.  This is useful for reusing middleware that performs validations, authentication etc:

app.post('/blocks', parseUrlencoded, function(req, res) {
  // parseUrlEncoded runs first, then the callback
  ...
});

Form data is available on request.body object.

Routes

app.route takes a route as an argument, and returns a route object which handles all requests to the given path. Can use this with chaining (chaining means calling functions on the return value of the previous functions):

app.route('/blocks')
.get(function(req, res) { ... })
.post(function(req, res) { ... });

app.all matches all HTTP verb requests.