A few problems here: as per the official express documentation for how to handle 404's, you need to move that 404 handler. Express evaluates routes "top down", so your 404 handler is currently kicking in for everything.
Also, no need for the http module, express is a web server, it already gives you app.listen to start the server.
But the most import thing is that routers are their own thing. By using them, you are creating a routing context that is isolated from the rest of the app, which includes having its own params object that will only contain the parameters defined by the router itself, so because your /zip-get route has no params, the req.params object will be empty inside the router's middleware chain.
However, inside the app.use middleware chain, which has a path that does have parameters in it, req.params will have all the values you'd expect, so: copy the values you need from req.params into res.locals as part of your app.use middleware chain, so that any downstream middleware (which includes downstream routers) has access to them.
import express from "express";
const app = express();
const router = express.Router();
router.get('/zip-get', (req, res) => {
console.log(`zip-get stored values:`, res.locals);
res.send('Done');
});
function copyParams(req, res, next) {
res.locals = {...req.params};
console.log(`app level params:`, req.params);
next();
}
app.use('/v1/users/:userId/zip/:zipNumber/address', copyParams, router);
// This has to come last.
app.use((req, res, next) => {
res.status(404).json({
error: 'path not found',
});
});
app.listen(8081, () => console.log(` http://localhost:8081`));
Alternatively, you can tell the router that it should preserve params when you call new Router by passing mergeParams: true as an option, but then you need to ask yourself why you're using a router at all: express is based on the concept of using a middleware chain to do "individual bits of work, based on the current context", so any code that relies on turning :userId and :zipNumber into real things should be kicking in before you hit the router middleware, with the intermediary data stored in res.locals. The way you've written things, /zip-get should not be doing anything with those parameters, because it is not responsible for them.
Instead, organize your API by what it needs to do, e.g. have a truly minimal main file:
import express from "express";
import userRoutes from "./routes/user.js";
const app = express();
app.use('/v1/users', userRoutes);
app.use((_req, res, _next) => {
res.status(404).json({
error: 'path not found',
});
});
app.listen(8081, () => console.log(` http://localhost:8081`));
With the user routes being responsible for users, and only users:
import express from "express";
import db from "./somewhere-or-other.js";
import zipRoutes from "./zip.js";
...
function findUser(req, res, next) {
db.getUserById(req.params.userId, (err, user) => {
if (errr) {
return next(err);
}
res.locals.user = user;
next();
});
}
const userRoutes = express.Router();
userRoutes.use('/:userId/zip', findUser, zipRoutes);
userRoutes.use('/:userId/something-else', findUser, someOtherRoutes);
export default userRoutes;
With a separate zip routes handler:
import express from "express";
import db from "./somewhere-or-other.js";
...
function getZipObject(req, res, next) {
zipManager.getZipObject(req.params.zipNumber, (err, zipData) => {
if (errr) {
return next(err);
}
res.locals.zip = zipData;
next();
});
}
const zipRoutes = express.Router();
zipRoutes.get('/:zipNumber/address/zip-get', getZipObject, (req, res) => {
// Render the page for this route, with res.locals as its context
// so that the page template can access the user and zip data.
res.render(`zip-get.html`, res.locals);
});
export default zipRoutes;
And note that we're terminating in a function that does nothing other than render the appropriate template as page response. All the work that needed to happen should, by the time we hit the final response function, have already been done and turned into res.local data that can be passed straight into the template rendering call.
addressRouter, show its code. No way to tell whether you simply have a typo, called the wrong function, or wrote something wild and crazy that could never work in the first place =)console.log('GET: /zip-get: req: ', req);in the fileaddressRouter.jsI am logging thereqobject and in the logs I could seeparams: {}is empty, accessing it will result in{}. To check the value of thereq.paramsI don't need to access it and print empty object, I can clearly make out from the logs that it is empty. I hope it is clear.httpif you're using express: your app already hasapp.listen()built in.