I'm doing an API in nodejs with express as router.
Now i'm trying to implement an client-id and an apikey to add some security to the API, and the problem that i'm facing is the next:
One of my API call is like this:
router.get("roles/get-objects/:mail/:filter*?")
So this means, that i can request an object like this:
/roles/get-objects/mail#mail.com/customer
Now the tricky part begins... when I needed to stablish a middleware to read an client-id and an apikey to verify that the client is authorized to se the API, so I did this:
In the declaration of the middleware, I use this wildcard:
router.all('/*', function (req, res, next) {
XXXX})
The thing is, I have tried in the middleware, as a wildcard everything...
I want that any API call is filtered thru that middleware, but apparently I can't find the right wildcard for it...
When I use /roles/* as wildcard, if I do a request to /roles it does work, but when I use the complete URL like: /roles/get-objects/mail#mail.com/customer it doesn't go thru my middleware.
So anybody has any idea? i'm starting to loose my mind
Thank you so much to all of you!
EDIT:
Now i'm using this middleware declaration:
router.use(function (req, res, next) {XXXX})
So when I call:
/roles/get-objects/
It's executed, the problem is when I add the email to the route:
/roles/get-objects/mail#mail.com
The app goes directly to the route that i have for that, but omits my middleware:
router.get("roles/get-objects/:mail",
I don't understand why is this happening, apparently everything should go thru my middleware first, or am I wrong?
If you want to establish a middleware to check all HTTP request whose URL starting with /roles/, the middleware should be placed before any other specific router definition:
router.use('/roles', function(req, res, next) {...});
...
router.get('/roles/get-objects/:mail', ...);
If the middleware is defined after specific route, when HTTP request comes in, the specific route is targeted and processed, the middleware won't be executed any more:
router.get('/roles/get-objects/:mail', ...);
...
router.use('/roles', function(req, res, next) {...}); // This middleware logic won't execute when request is sent to '/roles/get-objects/some-email', as the request has already been handled and response is already sent to browser.
Related
I've created a NodeJS Express app. But my express route is invocking multiple routes function, one after another, but I only need one at a time.
My express app.js
app.use(routes)
Express router:
const router = express.Router();
router.post("/product", controller.productFunction)
router.post("/user", controller.userFunction)
router.get("/:id", idController.getId)
Whenever I create a post request for "/product" route, first the productFunction is invocked, but then the "/:id" routes getId function is also get invocked. Same thing happen for /user route as well. Always /:id route is getting invocked.
Is there any way to prevent this?
I even tried this way, but after the homepage loading then again it invockes getId function.
app.get("/", (req, res, next) => {
res.sendFile(..........);
});
app.use(routes);
I am sure that this is not an issue with the router itself.
You can't skip from POST to GET handling. So invocations are caused by different requests.
router.get("/:id", idController.getId) kind of wild card, and <server_url>/favicon.ico will trigger it
If you check it via browser it tries to get favicon or smth else and invokes this handler.
Try to make POST request via curl/Postman and idController.getId should not be called.
It is risky to serve static and process requests on a same level.
You can add some prefix to all your request, like that app.use('/api', routes); then static file will be available on /<file_name> and all server logic will be under /api/<request>
In my NodeJs/express based application, I am authorizing calls to all the endpoints by using the following middleware.
app.use(restrictByCookieMiddleware);
I want to authorize all endpoints except one i.e. I don't want "restrictByCookieMiddleware" middleware to run for "/metrics" endpoint. Is there a way to escape one endpoint?
Here, I found some examples that matches endpoint for which middleware should run, I am looking for a solution that skips one.
Your have a couple of choices:
First, you can just define the one exception route handler BEFORE the middleware. Then, it will handle that route and the routing will never get to the middleware.
app.get("/login", (req, res) => {
// handle that one special route here
});
// all other routes will get this middleware
app.use(restrictByCookieMiddleware);
Second, you can make a wrapper for the middleware that compares to the one specific route and skips the middleware if it's that route:
app.use((req, res, next) => {
// shortcircuit the /login path so it doesn't call the middleware
if (req.path === "/login") {
next();
} else {
restrictByCookieMiddleware(req, res, next);
}
});
// then, somewhere else in your code would be the /login route
app.get("/login", ...);
Third, if you have multiple routes that you want to skip the middleware for, you can segment things by router. Create a router for the non-middleware routes and put all of them on that router. Hook that router into the app object first.
Then, create a second router that contains the middleware and has all your other routes on it.
Place that specific route, you want to exclude, before this line:
app.use(restrictByCookieMiddleware);
So this will solve your problem.
I would like to use the method route() on an express router to service a specific route with different HTTP methods. The following code works fine:
var express = require('express');
var router = express.Router();
router.route('/register')
.get(adm.signUpForm)
.post(adm.signUp);
However, when trying to use a middleware on the post route, I'm getting stuck. The following code works:
// LOGIN processing
router.post('/login', passport.authenticate("local", {
successRedirect: '/',
failureRedirect: '/login'
}), function(){
//empty
});
Here, the middleware function passport.authenticate(...) is called to check if the user credentials are valid or not. Authenticated users get re-directed to the homepage at "/"; Unknown users (or with incorrect password) get re-directed back to the "/login" form.
Now, I would like to re-factor this code and use something similar to the code example shown above (sign-up route), i. e. I would like to use router.route('/login).xxxx to service HTTP request xxxx on route '/login'. How can I tell express to use my passport.authenticate middleware function on the POST request to '/login'?
router.route('/login')
.get(adm.loginForm)
.post(<my-middleware-function ???>, adm.login);
... where adm.loginForm is the end-point function that issues the login form upon a GET request to /login and adm.login is the end-point function that should be called when the server receives a POST request on this route, i. e. once the login form is submitted.
To the best of my knowledge, the express (4.x) documentation doesn't mention anything about installing a middleware function for a specific route and (at the same time) a specific HTTP request. I know that router.route('/login').use() can be used to install a middleware function for all HTTP requests on this route, but I only want my middleware to be called upon POST requests.
Any suggestions? Thanks.
You can add them where you mentioned:
router.route('/login').post(checkPassport, adm.login)
You can also chain them together:
router.route('/login').post(checkPassport).post(adm.login)
checkPassport is the middleware you'll need to write that handles the passport authentication logic
I have a Node.js restful API. The problem I am having is that I am not sure why I am not able to see the request headers inside the middleware route.use(), however, it is visible inside get method router.get('/',function(req,res){}).
Can you someone please why is this case or what do I have to do get it visible inside
router.use(function(req,res,next){ next();});
Try something like his
router.use(function (req, res, next) {
console.log(req.headers['header_name']);
if (!req.headers['header_name']) return next('router')
next()
})
To skip the rest of the router’s middleware functions, call next('router') to pass control back out of the router instance.
I have a simple app, built with the help of node.js and express. This app has multiple routes and basic login/logout mechanics. I want all routes to redirect to a login form if the user is NOT logged in. This can be done by inserting auth checker lines into each route file.
The question is :
Is it possible to chain the routes to push all requests through login checker route and then pass it to the requested one without writing anything to existing route files?
E.g. existing routes are "/", "/upload", "/login", "/logout".
I want the request to get or post "/upload" to be first processed by "/login" route and then by "upload" route.
Yes, you can chain handlers in a route. Your handler definition should be like
routehandler(req, res, next){
//send response directly
//or call next to call the next handler
}
You can then put multiple handlers in the order you want:
app.get('/server', ensureAuthenticated, housekeeping, routes.server.get)
Here ensureAuthenticated and housekeeping dont send the response just call next(). The last one returns the resulting page.
Please see you would want a different handler than what you use for login. Login page would do authentication, rest pages should just check if the user is authenticated or not. The difference would be clear if you are using sessions.
The args for the route handlers are the same as that of middlewares. Those are :
(err, req, res, next) Error handlers
(req, res, next) Non-error handlers
A trivial variation of above is that next can be left out if it is the end function you want in callback chain. You cannot have other args apart from these. You can see the how they are called here (line 154).
A route consists of method, route-match and callback array. Like the middlewares the callback chain is executed sequentially for a specific route until response is returned or error is thrown.