Hapi nested routing

后端 未结 3 571
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-02-12 15:26

Suppose I want to have REST endpoints which look roughly like this:

/projects/
/projects/project_id 

/projects/project_id/items/
/projects/project_id/items/item         


        
3条回答
  •  孤城傲影
    2021-02-12 15:51

    What you're looking for is something similar to Express's Router. In fact, Express does a good job of burying the usefulness of this feature so I'll re-post an example here:

    // routes/users.js:
    // Note we are not specifying the '/users' portion of the path here...
    
    const router = express.Router();
    
    // index route
    router.get('/', (req, res) => {... });
    
    // item route
    router.get('/:id', (req, res) => { ... });
    
    // create route
    router.post('/', (req,res) => { ... });
    
    // update route
    router.put('/:id', (req,res) => { ... });
    
    // Note also you should be using router.param to consolidate lookup logic:
    router.param('id', (req, res, next) => {
      const id = req.params.id;
      User.findById(id).then( user => {
        if ( ! user ) return next(Boom.notFound(`User [${id}] does not exist`));
        req.user = user;
        next();
      }).catch(next);
    });
    
    module.exports = router;
    

    Then in your app.js or main routes/index.js where you assemble your routes:

    const userRoutes = require('./routes/users')
    
    // now we say to mount those routes at /users!  Yay DRY!
    server.use('/users', userRoutes)
    

    I'm actually disappointed to find this SO post with no other responses so I'll assume there's nothing out of the box (or even a third-party module!) to achieve this. I imagine it might not be too difficult to create a simple module that uses functional composition to remove duplication. Since each of those hapi route defs is just an object it seems like you could make a similar wrapper like the following (untested):

    function mountRoutes(pathPrefix, server, routes) {
      // for the sake of argument assume routes is an array and each item is 
      // what you'd normally pass to hapi's `server.route
      routes.forEach( route => {
        const path = `${pathPrefix}{route.path}`;
        server.route(Object.assign(routes, {path}));
      });
    }
    

    EDIT In your case since you have multiple layers of nesting, a feature similar to Express's router.param would also be extremely helpful. I am not terribly familiar with hapi so I don't know if it already has this capability.

    EDIT #2 To more directly answer the original question, here is a hapi-route-builder has a setRootPath() method that lets you achieve something very similar by letting you specify the base portion of the path once.

提交回复
热议问题