简体   繁体   中英

How to add express route if the app already listening?

I want to create automatic routing in express, currently i can read directory and add route manually from all available files, added route can also be updated if there are changes in route file

delete require.cache[require.resolve(scriptpath)];
var routescript = {};
try {
   routescript = require(scriptpath);
} catch (e){
   console.log('Express >> Ignoring error route: ' + route + ' ~ >' + scriptpath);
}
var stack_index = app._router.stack_map[route]
var stack = app._router.stack[stack_index];
if (stack) {
    app._router.stack[stack_index].handle = routescript;
    console.log('Replace Route Stack \'' + route + '\'');
} else {
    app.use(route, routescript);
    var stack_index = app._router.stack_map[route] = (app._router.stack.length-1);
    console.log('Add Route Stack \'' + route + '\'');
}

But those are only work only before app listen to port,

How to add / remove new route stack after the app listening to port?

One way i can think is close the server configure/add/remove the route the re listen, but i guess that is a bad practice

After poking around with express code, I found this:

router.get('/', function(req, res) {
  res.render('index', {
    title: 'Express'
  });
  console.log("adding route")

  addGet('/mypath', function(req, res) {
     res.send('hi')
  });
});

function addGet(path, callback) {
  Router = require('express').router;
  // We get a layer sample so we can instatiate one after
  layerSample = router.stack[0];

  // get constructors
  Layer = layerSample.constructor;
  Route = layerSample.route.constructor;

  // see https://github.com/strongloop/express/blob/4.x/lib/router/index.js#L457
  route = new Route(path);

  var layer = new Layer(path, {
    sensitive: this.caseSensitive,
    strict: this.strict,
    end: true
  }, route.dispatch.bind(route));
  layer.route = route;

  // And we bind get
  route.get(callback)

  // And we map it
  router.stack.push(layer);
}

So then open your browser at localhost and then at localhost/mypath it works!!!

I am so stupid....

Express 4 default is capable to add route even after it listening

So why i can't do it before? because on top of router layer stack, i add error handling layer stack, so any router layer i add after it, won't be reachable by request, because when the request is processed it will caught first by error handler layer.

so the correct method is as the following:

  1. I have to manage what index is the error handler stack layer located in app._router.stack , in this case it is some layer at the very end of array

  2. Add new route, ex: using app.use("/something", function(req, res, next){ res.send("Lol") })

  3. Remove the error handler layer stacks, and put it at the very end of the router stack array

    // in this case, error map is array // contain index location of error handling stack layer var error_handlers = app._router.stack.splice(error_map[0], error_map.length); app._router.stack.push.apply(app._router.stack, error_handlers);

Now you are ready to go.

Seven years later I share the same doubt as DeckyFx.

I need setup express stack on startup, then dynamically load "plugins" that have their own routers.

So after reading the current express documentation and not find any method to handle stack layers, I have integrate my own method based on the different answers read around here

It is simple:

  1. Remove stack tail, where UnknonwRouteHandler and ErrorRouteHandler are.
  2. Inject my new router/middleware.
  3. Add again stack tail routes.

My code:

// static tail layers definition    
_tailLayers = ['UnknownRouteHandler','ErrorRouteHandler'];

// delete tail layer with filter    
app._router.stack = app._router.stack.filter(layer => !_tailLayers.includes(layer?.name));

// inject new route
app.use('/', MyRouter);

// inject again stack tail 
app.use(UnknownRouteHandler);
app.use(ErrorRouteHandler);

It's works!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM