npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

detour

v1.3.4

Published

Resource-oriented routing: Route to objects instead of functions for better code-reuse and organization.

Downloads

90

Readme

detour

Build Status Coverage Status NPM version

Detour is a router for node.js web applications.

Detour is different from sinatra-style routers (like express's router) because you route urls to objects (that have http methods) instead of to http methods.

Rationale: If you have multiple http methods implemented for a given url (like a lot of APIs do), this style of routing will be much more natural and will vastly improve your code organization and re-use. With object routing, it's much simpler to keep the related handlers together, but separated from unrelated handlers (often even in another file/module).

It works for node.js' standard HTTP server, as well as express and connect applications.

Examples:

Using it in a plain node.js web app:

  var detour = require('detour');
  var http   = require('http');
  var router = detour();

  router.route('/', {
    GET : function(req, res){
      res.end("GET works!");
    },
    POST : function(req, res){
      res.end("POST works too!");
    }
  });

  http.createServer(function(req, res){
    router.middleware(req, res);
  }).listen(9999);

Using it in an express app:

  var detour = require('detour');
  var express = require('express');
  var app = express();
  var router = detour();
  app.use(router.middleware);
  
  router.route('/', {
    GET : function(req, res){
      res.end("GET works!");
    },
    POST : function(req, res){
      res.end("POST works too!");
    }
  });

Path Variables:

A simple example:

  router.route('/test/:test_id', {
    GET : function(req, res){
      res.end("GET works: " + req.pathVar.test_id);
      // a request to /test/1234 will have output like this:
      //   GET works: 1234
      
      // req.pathVar is a hash of all name value pairs pull from the
      // request url
    },
  });

In the example above, you can see that the path string sent to the router (/test/:test_id) uses the same format as express. Regular expressions are also allowed.

You can also see from the example that within a route handler, req.pathVar will have all the variables collected from your route.

connect-style middleware

Detour supports connect-style middleware like most node.js frameworks (including express). Example:

  var detour = require('detour');
  var router = detour();
  router.use(someMiddleware);

The middleware stack for detour runs after the route has been determined, but before any other processing. The entire routed resource object will be available at req.detourHandler if you want to do any special handling in your middleware that are related to its contents.

This makes Detour extremely extensible on a resource-by-resource basis. For example, if you write a resource object like this:

  router.route('/test/:test_id', {
    mustBeAuthenticated : true,   // <-- NB: non-standard property
    GET : function(req, res){
      res.end("GET works: " + req.pathVar.test_id);
    },
  });

...you can write a middleware that acts according to that data before the handler for GET is called.

collections

In addition to regular object routing, For the sake of convenience, Detour also supports collection-routing where two resource objects can be routed in a collection-member relationship at the same time.

Here's an example:

var router = new Router();
router.collection('/test/:testid', {
  collection : {
    GET : function(req, res){
      res.end('collection here!');
    }
  },
  member : {
    GET : function(req, res){
      res.end('member here! ' + JSON.stringify(req.pathVar));
    }
  }
});

Note: the object being routed has two properties: collection and member, with each being a resource object on its own. The member resource object will be routed to the given path (/test/:testid in this case), and the collection resource object will be routed to the parent path (/test in this case).

This feature can be useful if you have resources that follow this pattern and you want to keep these two similar resources together in the same file.

Method defaults and overrides:

OPTIONS handling:

There is a default OPTIONS response for any route but you can over-ride it like this:

router.on('OPTIONS', function(req, res, resource){
  // resource is the object you routed.  You can loop through the methods on it here if you want!
  res.writeHead(200);
  res.end("options, options, options!");
});

HEAD handling:

There is a default HEAD response for any route with a GET, but you can over-ride it like this:

router.on('HEAD', function(req, res, resource){
  // resource is the object you routed.  You can call resource.GET() from here if you want!
  res.writeHead(200);
  res.end("doesn't matter what I type here.  node will not send output on a HEAD request")
});

Error defaults and overrides:

405 handling:

The correct http response for a method that an existing url doesn't support is a 405. You can over-ride the default like this:

router.on(405, function(req, res, resource){
  // resource is the object you routed.  You can loop through the methods on it here if you want!
  res.writeHead(405);
  res.end("this resource doesn't support that method! ");
});

404 handling:

There is a default 404 response for any route that doesn't match, but you can over-ride it like this:

router.on(404, function(req, res){
  res.writeHead(404);
  res.end("nope. couldn't find that!")
});

(NOTE: this only works if the middleware doesn't get a third parameter -- typically called next() -- passed to it, otherwise next() is used for 404s as you'd expect from a middleware.)