Dynamic dropping of handlers in restify
Asked Answered
V

1

10

Context

I am trying to build a dynamic server with restify (2.6.2) where services are to be installed and uninstalled once the server is started. I realized this can be seen as something odd but it has sense in the context of a DSL oriented project. To achieve this goal I have implemented the following functions:

var install = function (path, method, handler) { 
    var id = server[method](path, function (request, response) { // [1]
        handler (request, response);
    });
    return id;
} 
var uninstall = function (id) { 
    delete server.routes[id]; // [2]
}

The install function, installs a handler in the route specified by a path and a method name [1]. The uninstall function, uninstall the handler by dropping it from routes [2]. This capabilities are exposed as services by the following code:

var db = ...
var server = restify.createServer ()
    .use (restify.bodyParser ({ mapParams: false }))
    .use (restify.queryParser ())
    .use (restify.fullResponse ());
service.post ('/services', function (request, response) {
   var path    = request.body.path;
   var method  = request.body.method;
   var handler = createHandler (request.body.dsl) // off-topic
   var id = install (path, method, handler)
   db.save (path, method, id); // [3]
});
service.del ('/services', function (request, response) {
   var path   = request.body.path;
   var method = request.body.method;
   var id     = db.load (path, method); // [4]
   uninstall (id);
});

In post method [3], a handler is obtained from body (it is off-topic how this is undertaken) and a service is installed storing the returned id in a database. The del method [4], retrieves the id from the database and invokes the uninstall function.

Problem

This code has been unit-tested and it works properly but a malfunction is reached when I try to execute an install/uninstall sequence like the following one. In this example, please suppose that the body of all requests contains the same path, http verb and proper content to build a correct handler:

/*
post: /services : Installed          -> ok
del:  /services : Resource not found -> ok
post: /services : Resource not found -> Error :(
*/

In the first install, handler is executed when resource is acceded via path and verb. The uninstall request is correctly fulfilled because a Resource not found message is obtained when path is visited on verb. Nevertheless, when the same body is installed secondly in the server, a Resource not found is returned when path is acceded on verb.

I suppose that the error is in [2] because, may be, I am not using the correct unregister strategy for restify.

Question

How can be effectively dropped handlers from restify once the server is started?

Variate answered 15/6, 2015 at 3:12 Comment(1)
As an aside, isn't this incredibly risky from a security standpoint? You're allowing arbitrary code to be passed in that will be executed when a certain endpoint is hit, which is also passed in.Resting
R
4

After looking at the restify source I found the following, which you may want to try instead of simply 'delete' (https://github.com/restify/node-restify/blob/master/lib/server.js).

/*
* Removes a route from the server.
* You pass in the route 'blob' you got from a mount call.
* @public
* @function rm
* @throws   {TypeError} on bad input.
* @param    {String}    route the route name.
* @returns  {Boolean}         true if route was removed, false if not.
*/
Server.prototype.rm = function rm(route) {
    var r = this.router.unmount(route);

    if (r && this.routes[r]) {
        delete this.routes[r];
    }

    return (r);
};
Resting answered 17/7, 2015 at 5:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.