I have the following code with 3 independent routers
const Express = require("express")
const app = Express()
const usersRouter = Express.Router()
const productsRouter = Express.Router()
const storeRouter = Express.Router()
productsRouter.use((_, res, next) => {
res.send("products fail")
//next()
})
storeRouter.use((_, res, next) => {
res.send("store fail")
//next()
})
usersRouter.route("/users")
.get((_, res) => res.send("users"))
productsRouter.route("/products")
.get((_, res) => res.send("products"))
storeRouter.route("/store")
.get((_, res) => res.send("store"))
app.use(usersRouter)
app.use(productsRouter)
app.use(storeRouter)
app.listen(80, () => console.log("running"))
But every time I request /store route it pass through productRouter middleware which is assigned only to it.
I can't understand this behavior.
Why is this? How can I manage independent middlewares for each one?
GET /store 200
products fail
Expected
GET /store 200
store fail
CodePudding user response:
When you do this:
app.use(productsRouter)
that sends ALL requests to the productsRouter and thus its middleware runs for all requests. So, when you have this:
productsRouter.use((_, res, next) => {
res.send("products fail")
//next()
});
That will run on every single request.
If you want the router to only see certain requests, then register the router on a path instead so the router only gets requests destined for a certain path.
app.use("/products", productsRouter)
And, then remove the path itself from the router's routes since the path will have already been filtered.
CodePudding user response:
In order to achieve the expected behavior, you will have to make little changes to your code.
First: Take this approach, since it will allow you to keep everything clean and separated (this is crucial if you want to implement specific middlewares for each route).
usersRouter.
.get("/", (req, res) => res.send("users"))
productsRouter.route
.get("/", (req, res) => res.send("products"))
storeRouter.route("/store")
.get("/", (req, res) => res.send("store"))
app.use("/users", usersRouter)
app.use("/products", productsRouter)
app.use("/store", storeRouter)
Instead of this one
usersRouter.route("/users")
.get((_, res) => res.send("users"))
productsRouter.route("/products")
.get((_, res) => res.send("products"))
storeRouter.route("/store")
.get((_, res) => res.send("store"))
app.use(usersRouter)
app.use(productsRouter)
app.use(storeRouter)
Second:
Uncomment the next() call on your middlewares, identify the request parameter on their callbacks and store them in variables (not crucial, but improves readability)
const productsMiddleware = (req, res, next) => {
res.send("products fail")
next()
}
const storeMiddleware = (res, res, next) => {
res.send("store fail")
next()
}
Third: Pass the middleware you want to apply to a specific controller right after the route and before the actual controller declaration on your router. E.G.
usersRouter.
.get("/", (req, res) => res.send("users"))
productsRouter.route
.get("/", productsMiddleware, (req, res) => res.send("products"))
storeRouter.route("/store")
.get("/", storeMiddleware, (req, res) => res.send("store"))
By doing all this things, you'll end up with "independent middlewares" that only apply to the specified route/controller.
