
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
json-router
Advanced tools
An alternative mobile-focused router/rpc middleware that uses the JSON body instead of URL slugs to route requests
An alternative mobile-focused router/RPC middleware that uses the JSON body instead of URL slugs to route requests.
The major advantage of this approach is that it easily allows multiple server requests to occur per HTTP request. This reduces latency in your client with network constrained devices like mobile apps.
JSON Router works similar to javascript Function.apply() by taking a name and a variable number of arguments via an array. The request object can handle an array of server requests. The values returned by each request handler and will be aggregated into a JSON array which will be returned to the client.
JSON Router can take an optional callback if you would like to do custom handling on the result object.
npm install --save json-router
For the simple use case, JSON Router is straightforward. On the server, you pass the router a variable number of handler names and handler functions. You then pass your server (express, connect, restify, etc.) the router middleware after the JSON body parser.
var express = require('express');
var bodyParser = require('body-parser');
var jsonRouter = require('json-router');
var app = express();
app.use(bodyParser.json());
jsonRouter.newRequest("myRequestName1", function(context, arguments, callback) {
// ...
return callback(null, retValue);
});
jsonRouter.newRequest("myRequestName2", function(context, arguments, callback) {
// ...
return callback(null, [retValue1, retValue2]);
});
app.use(jsonRouter.middleware());
On the client, you send the server a JSON object in the HTTP body using POST. The middleware looks for JSON objects that have the top-level property 'jsonRoute' (this can be changed with the routeProperty option). If this property does not exist, the server will continue on with the middleware chain.
{
"jsonRoute": {
"name": "myRequestName1",
"arguments": [ "foo" ]
}
}
JSON router will reply with a JSON object containing the result
{
"requestId": "myRequestName1",
"result": "myResult"
}
JSON Router can take multiple requests per HTTP request
{
"jsonRoute": [
{
"name": "myRequestName1",
"arguments": [ "foo" ]
},
{
"name": "myRequestName2",
"arguments": [ "arg1", "arg2", "arg3" ]
}
]
}
Or you can use an object-literal notation where each key is the request's requestId.
{
"jsonRoute": {
"myRequestName1": {
"arguments": [ "foo" ]
},
"myRequestName2": {
"arguments": [ "arg1", "arg2", "arg3" ]
}
}
}
Similarly, the router will reply with multiple results
{
"myRequestName1": {
"requestId": "myRequestName1",
"result": "myResult"
},
"myRequestName2": {
"requestId": "myRequestName2",
"result": [ 1, 2, 3 ]
}
}
If there is an error, the response object will use the error property instead of a non-200 HTTP code. This is because it may be possible that some request handlers succeed while other fail.
{
"myRequestName1": {
"requestId": "myRequestName1",
"error": "My Error String"
},
"myRequestName2": {
"requestId": "myRequestName2",
"result": [ 1, 2, 3 ]
}
}
If you would like to execute the same handler function multiple times in a single request, you need to give each request a unique requestId (this defaults to the name if not provided)
{
"jsonRoute": [
{
"name": "myRequestName1",
"requestId": "passFooToReq1",
"arguments": [ "foo" ]
},
{
"name": "myRequestName1",
"requestId": "emptyReq1",
"arguments": []
}
]
}
Normally, JSON Router will run all requests concurrently. However, this behavior can be modified using dependencies between requests. The property dependsOn causes JSON Router to build a dependency tree to execute the requests. In this example, myRequestName2 will run after myRequestName1 (myRequestName3 will run concurrently with myRequestName1).
{
"jsonRoute": [
{
"name": "myRequestName1",
"arguments": [ "foo" ]
},
{
"name": "myRequestName2",
"dependsOn": "myRequestName1",
"arguments": [ "bar" ]
},
{
"name": "myRequestName3",
"arguments": [ "baz" ]
}
]
}
If a request handler fails, all dependent children requests will be cancelled and not run.
{
"myRequestName1": {
"requestId": "myRequestName1",
"error": "My Error String"
},
"myRequestName2": {
"requestId": "myRequestName2",
"error": "Request skipped due to failed dependency"
},
"myRequestName3": {
"requestId": "myRequestName2",
"result": [ 1, 2, 3 ]
}
}
The handler function should provide the follow signature
handlerFunc = function(context, arguments, callback)
The context object provide help object and functions to use in your handler
| Property | Type | Description |
|---|---|---|
name | String | Request handler name |
requestId | String | Request handler requestId (by default is equal to name) |
dependsOn | String | The requestId of the request handler that this request depends on (if any) |
parentResult | Object | The result that the parent request returned (if dependsOn exists) |
request | Object | The request object used by JSON Router |
httpReq | Object | HTTP request object passed to the middleware |
httpRes | Object | HTTP response object passed to the middleware (don't use directly in handler function) |
getResult | function | getResult(reqId)Returns the result object of requestId if it has finished running |
getRequest | function | getRequest(reqId)Returns the request object of requestId |
enqueueRequest | function | enqueueRequest(reqName, args, reqId, dependsOn)Dynamically adds a request to be run |
cancelRequest | function | cancelRequest(reqId)Dynamically cancels a request |
getRequestHandler | function | getRequestHandler(name)Returns the request handler function |
newRequest | function | newRequest(name, handler)Adds a new request handler function to JSON Router |
Arguments will always be an array type
The callback to the handler function accepts the following signature
callback = function(err, result)
JSON Router can take options and a custom callback function when instantiating the middleware function.
app.use(jsonRouter.middleware(opts, callback));
The following options are supported
| Option | Type | Default | Description |
|---|---|---|---|
routeProperty | String | jsonRoute | The top-level property that indicates the incoming JSON object should be handled by the router middleware |
flattenSingle | Boolean | true | If there is only one request handler, the response object will be flattened instead of being keyed by one requestId |
sendObject | Boolean | true | If option is false, the response object will return an array of responses instead of a requestId keyed object |
If you would like to handle the results of the JSON router manually, you can provide a callback function with the following signature:
callback = function(req, res, results, next)
By default, JSON Router uses the following callback function to send a JSON object to the client
function(req, res, results, next) {
return res.json(results);
}
JSON router emits events that can be subscribed to
| Event | Signature | Description |
|---|---|---|
status | function(reqId, status, req) | emitted whenever a requests' status changes ( waiting, cancelled, running, finished) |
Example
var jsonRouter = require('json-router');
jsonRouter.on('status', function(reqId, status, req) {
console.log("Request: " + reqId + " changed to " + status);
});
Object literal notation for dependencies.
FAQs
An alternative mobile-focused router/rpc middleware that uses the JSON body instead of URL slugs to route requests
The npm package json-router receives a total of 9 weekly downloads. As such, json-router popularity was classified as not popular.
We found that json-router 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
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.