
Security News
Socket Releases Free Certified Patches for Critical vm2 Sandbox Escape
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.
express-resourceful-routing
Advanced tools
Building simple, easy restful routes for nodejs & expressjs, with a viewable routing table
Build simple, easy restful routes for nodejs & expressjs, with a viewable routing table.
Resource routing provides:
npm install resource-routing --save
Resource Routes expects all your controllers to be in the same directory. A good recommendation is PROJECT_ROOT/controllers or PROJECT_ROOT/app/controllers.
Resource Routes expects all controller to be named with common convention of [entities]_controller.js, like 'posts_controller.rb' or 'comments_controller.rb'
For example, if you have a User resource or model you want to manage. Resource Routes expects you to manage it with a users_controller.js file. If they don't match this convention, they may not be found.
Resource Routes depends on the express.js engine.
Example usage:
// get your app
var express = require('express');
var app = express();
// get your controller path. NOTE: resolve to full path
var path = require('path');
var controller_dir = path.resolve(./controllers");
// build your resource routing urls
var routing = require('resource-routing');
routing.resources(app, controller_dir, "users");
That's it. You now have restful routing for your User model.
The resources() function takes a minimum of three parameters:
The simplest usage is:
routing.resources(app, controller_dir, "users", {}); // last param optional
This will build the 14 standard restful routes for you:
Method URL Handler
GET /users users_controller.index
GET /users.format users_controller.index
GET /users/new users_controller.new
GET /users/new.format users_controller.new
POST /users users_controller.create
POST /users.format users_controller.create
GET /users/:id users_controller.show
GET /users/:id.format users_controller.show
GET /users/:id/edit users_controller.edit
GET /users/:id/edit.format users_controller.edit
PUT /users/:id users_controller.update
PUT /users/:id.format users_controller.update
DELETE /users/:id users_controller.destroy
DELETE /users/:id.format users_controller.destroy
If the controller does not exist, the routes will not be created.
If a specific expected attribute on the controller do not exist or is not a function, the relevant route will not get created.
The functions should be defined as normal express request handlers:
function(req, res) {};
A fourth parameter, an options object, may be included to add or restrict route creation. Several option attributes are recognized:
An array of standard route names. These standard routes will be excluded from the route creation process. They will not be created.
Example:
routing.resources(app, controller_use, "users", { except: ["delete"] } };
This will create six of the seven standard routes, plus their .format variants, but the delete route
will not be created.
An array of standard route names. ONLY these standard routes will be created. Other standard routes not included in this list will be excluded from the route creation process.
Example:
routing.resources(app, controller_use, "users", { only: ["index", "show"] } };
This will suppress creation of the new, create,
update, edit, and delete routes . In this case your user resource
will be only have read-only routes exposed.
If only is included in the options, the except option is ignored.
If you need add additional custom member routes, you can declare them with the member
options attribute. It takes an array of arrays, where each of the sub-arrays is
two or three elements.
Example:
routing.resources(app, controller_dir, "users", {member:[
["get", "foo", "bar"],
["get", "baz"]
]});
Will generate (in addition to the regular routes:
Method URL Handler
get /users/:id/foo users_controller.bar
get /users/:id/foo.:format users_controller.bar
get /users/:id/baz users_controller.baz
get /users/:id/baz.:format users_controller.baz
If you need additional custom collection routes, you can declare them with the collection
options attribute. It works the same way as the member attribute, but the base url used does not include :id.
Instead it uses the general controller url.
Example:
routing.resources(app, controller_dir, "users", {collection: [
["get", "reset_request", "reset"]
]});
Will generate:
Method URL Handler
get /users/reset_request users_controller.reset
get /users/reset_request.:format users_controller.reset
String value. Controller file. Overrides the automatic model-to-controller conversion (where passing in "users" will automatically try to load "users_controller") and let's you declare which controller you will be using.
For example:
routing.resources(app, controller_use, "users", { using: "members_controller" };
Will create:
Method URL Handler
get /users members_controller.index
get /users.:format members_controller.index
get /users/new members_controller.new
get /users/new.:format members_controller.new
[etc]
String value. Url prefix. If defined, it is prepended to the generated url path. Useful for namespaces or url versioning:
For example:
routing.resources(app, controller_use, "users", { prefix: "api/1.0" };
Will create:
Method URL Handler
get /api/1.0/users members_controller.index
get /api/1.0/users.:format members_controller.index
get /api/1.0/users/new members_controller.new
get /api/1.0/users/new.:format members_controller.new
[etc]
Nested resources are supported. By passing more than the minimum number of paramaters, the extra strings are assumed to be parent resources. For example, a call like:
routing.resources(app, controller_dir, "users", "tables, "stories", {}); // again, last param optional
Resource Routing will build the routes for stories, as a nested resource for tables and users, and the request will include resource ids for the parent resourses.
These are the routes that will get created with that method call:
Method URL Handler
GET /users/:user_id/tables/:table_id/stories StoriesController.index
GET /users/:user_id/tables/:table_id/stories.format StoriesController.index
GET /users/:user_id/tables/:table_id/stories/new StoriesController.new
GET /users/:user_id/tables/:table_id/stories/new.format StoriesController.new
POST /users/:user_id/tables/:table_id/stories StoriesController.create
POST /users/:user_id/tables/:table_id/stories.format StoriesController.create
GET /users/:user_id/tables/:table_id/stories/:id StoriesController.show
GET /users/:user_id/tables/:table_id/stories/:id.format StoriesController.show
GET /users/:user_id/tables/:table_id/stories/:id/edit StoriesController.edit
GET /users/:user_id/tables/:table_id/stories/:id/edit.format StoriesController.edit
PUT /users/:user_id/tables/:table_id/stories/:id StoriesController.update
PUT /users/:user_id/tables/:table_id/stories/:id.format StoriesController.update
DELETE /users/:user_id/tables/:table_id/stories/:id StoriesController.destroy
DELETE /users/:user_id/tables/:table_id/stories/:id.format StoriesController.destroy
NOTE: None of the parent resource routes gets create. They will need their one resource call to have them defined, like so:
routing.resources(app, controller_dir, "users");
routing.resources(app, controller_dir, "users", "tables");
routing.resources(app, controller_dir, "users", "tables, "stories");
Declare your root or home url with the .root() method:
routing.root(app, controller_dir, "index", "home");
This creates multiple routes to IndexController.home.
GET / index_controller.home
GET /index.:format index_controller.home
GET /index index_controller.home
You can declare all arbitrary non-restful routes through the resource-routing interface.
There are two reasons to do this:
Resource routing provides a light wrapper around the traditional route express.js declaration.
Example:
Instead of doing this:
var tables_controller = require("./controllers/tables_controller");
app.get("/my_tables", table_controller.index")
Do this:
routing.get(app, controller_dir, "/my_tables", "tables#index")
It will generate the expected routes:
Method URL Handler
get /my_tables tables.index
get /my_tables.:format tables.index
The same restrictions for resource routes also apply here. If the controller cannot be found, the route is not created. If the controller action is not defined or is not a function, the route is not created.
If you have a lot of generated resource routes, you many want or need a convenient way to see all the routes. Resource Routing give you a way to do this.
var express = require('express');
var app = express();
var routing = require('resource-routing');
routing.expose_routing_table(app);
This enables a display of the routing table at a default location of: /routing-table. This display an html table of all the
internally generated routes. It does NOT include routes not added by resource-routing.
You can override the location of the routing table by passing an 'at' attribute in the options object:
routing.expose_routing_table(app, { at: "/my-routes" });
Some users may want to conditionally enable it. (i.e. in development, but not in production);
When generating routes, Resource Routing sets up a closure for dispatching your request handlers. The default implementation is:
function(handler, req, res){
handler(req, res);
}
The handler here is your controller action. The default closure does anything, it just
passes the request through.
But you can override this, providing your own closure do whatever you want:
routing.set_wrapper(function(handler, req, res){
console.log("CUSTOM WRAPPER");
var options = { extra_data: "example"};
handler(req, res, options);
})
You can define you own controller action method signature (making sure your controller actions implement the signature), set up some global logging or metrics. It's up to you.
NOTE: Async coding practices with callback handlers make come into play here.
This resets the handler wrapper back to the default, non-additive closure.
MIT. see License
FAQs
Building simple, easy restful routes for nodejs & expressjs, with a viewable routing table
We found that express-resourceful-routing demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.

Research
Five malicious NuGet packages impersonate Chinese .NET libraries to deploy a stealer targeting browser credentials, crypto wallets, SSH keys, and local files.

Security News
pnpm 11 turns on a 1-day Minimum Release Age and blocks exotic subdeps by default, adding safeguards against fast-moving supply chain attacks.