skip to Main Content

I’m building an express application that has a users table in its database and a friends table. The point of the friends table is to be a many-to-many table that keeps track of friend requests between users. Since friends are ultimately always going to be tied to users, I wanted my express routes for friends to be a child router to the users router. However, my req.params properties in the parent routes are not being passed down to my friends routes.

I’ve set up the users routes like this:

const friendRoutes = require("./friends");
const router = express.Router({ mergeParams: true });
router.use('/:username/friends', friendRoutes);

My only friends route for now is:

router.post("/request/:receiver", ensureCorrectUserOrAdmin, async function (req, res, next) {
    try{
        // validate that request follows friendNewSchema
        const validator = jsonschema.validate(req.body, friendNewSchema);
        if( !validator.valid ) {
            const errs = validator.errors.map(e => e.stack);
            throw new BadRequestError(errs);
        }

        // make new request with Friend.request
        console.log("Friend Request Body: ", req.body);
        console.log("Friend Request Params: ", req.params);
        const friendRequest = await Friend.request(req.params.username, req.params.receiver);
        console.log("Successfully made Friend Request: ", friend);

        // return json of friendRequest with a status code of 201
        return res.status(201).json({ friendRequest });
    }
    catch (err) {
        return next(err);
    }
});

The specific problem I am running into is that the route is /users/:username/friends/request/:receiver but the :username route variable is never defined when my friends route is called. I checked the middleware function and it never touches/modifies the req.params object. What should I do to get the child route to access the parent route variable?

2

Answers


  1. If req.params.username is still undefined or incorrect, here are a few things to check:

    • Middleware Order: Ensure that any middleware that manipulates req.params (if any) is not interfering with the expected values.
    • Route Definition: Double-check that all routes are defined in the correct order and that mergeParams: true is applied to the correct router (router in your case).
    • Logging and Debugging: Use console.log or debugging tools to inspect req.params at various points in your middleware chain to see how it’s being populated.

    Example of Middleware Issue:
    If there’s a middleware that runs before your route and modifies req.params, it could affect your expected behavior.
    For instance:

    router.use('/:username/friends', (req, res, next) => {
      // Some middleware that modifies req.params
      req.params.username = 'someDefaultUsername'; // This could override your intended behavior
      
      next();
    });
    
    router.post("/request/:receiver", ensureCorrectUserOrAdmin, async function (req, res, next) {
      // Now req.params.username might not be what you expect
    });
    

    Ensure no such middleware is unintentionally modifying req.params.username.

    Login or Signup to reply.
  2. Based on the additional information provided, it seems like your middleware order and route definitions are mostly correct, but there might still be an issue with how req.params is being handled between the parent and child routers.

    1. Check Middleware for Side Effects:
      Ensure that none of your middleware is inadvertently modifying req.params. The logParams middleware is useful for logging but verify that it doesn’t alter req.params.

    2. Minimal Reproduction of the Issue:
      Create a minimal version of your application to isolate the problem. This can help determine if the issue is with your current setup or something else in your larger codebase.

    Sample Minimal Reproduction

    Here’s a simplified example to reproduce your setup and verify the issue:

    const express = require('express');
    const app = express();
    
    // Middleware to log params
    function logParams(req, res, next) {
      console.log('Params:', req.params);
      next();
    }
    
    // Middleware to ensure correct user or admin
    function ensureCorrectUserOrAdmin(req, res, next) {
      // Simulate authentication without modifying req.params
      next();
    }
    
    // Friends router
    const friendsRouter = express.Router({ mergeParams: true });
    
    friendsRouter.post('/request/:receiver', ensureCorrectUserOrAdmin, async function (req, res, next) {
      console.log('Inside friends router:', req.params); // Should log both username and receiver
      // Simulate friend request logic
      res.status(201).json({ friendRequest: 'success' });
    });
    
    // Users router
    const usersRouter = express.Router({ mergeParams: true });
    
    usersRouter.use('/:username/friends', logParams, friendsRouter);
    
    // Main app
    app.use('/users', usersRouter);
    
    // Start server
    app.listen(3000, () => {
      console.log('Server started on port 3000');
    });
    

    Additional Checks

    • Parameter Names:
      Ensure there are no typos or mismatches in parameter names (:username and :receiver).

    • Express Version:
      Ensure you are using a compatible version of Express that supports mergeParams correctly.

    If the minimal reproduction works correctly, compare it with your actual application to identify differences. If the issue persists in the minimal example, it might be a deeper issue with Express or how routes/middleware are set up.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search