I am trying to write a middleware that creates a new method on app created with express(). For example, I would like to achieve the following:
app.use(myMiddleware())
// ...
app.newMethod() // added through the previous middleware
Is there a way to achieve this? A way I have thought of, as referenced in some other questions, is to pass in app itself as a param to my middleware so that I could tweak it:
app.use(myMiddleware(app))
// ...
app.newMethod() // ok, definitely doable
However, this does not seem elegant enough.
Also, req.app and res.app references won't work for me in this case, since the (req, res, next) => {} function returned by myMiddleware() only executes when receiving requests, while I possibly want to access the method before even app.listen() is called.
Is there a way I can achieve this?
It really doesn't make sense to add an app method in middleware. The purpose of middleware is to process an incoming request, either in preparation for later middleware or later request handlers or to just handle the request itself in the middleware.
Middleware gets called over and over during incoming requests. It should never be used for something that should just happen once and it should only be used for processing related to an incoming request.
while I possibly want to access the method before even app.listen() is called
So, that definitely has nothing to do with an incoming request then so using middleware is just not the right design choice.
If all you're trying to do is to add your own method to the app object, you can do that when you are initializing your server:
const app = require('express')();
// add my own method to the app object
app.myMethod = function(myArg1, myArg2) {
// put the implementation here
}
app.use(...);
app.get(...);
app.get(...);
app.listen(...);
Then, anywhere you want, you can call app.myMethod(...).
Related
I have been working on a typescript project. I have created a middleware to check users' subscription and do not want to let users access PUT and POST routes. But I still want them to be able to access GET and DELETE requests.
I know that the following line applies the checkSubscription middleware to all the requests on the route.
router.use(checkSubscription)
I only want the middleware to run if the request type is PUT or POST.
I could do the following, of course
router.get("/endpoint1", controller1);
router.put("/endpoint2", checkSubscription, controller2);
router.post("/endpoint3", checkSubscription, controller3);
router.delete("/endpoint4", controller4);
Notice that the above PUT and POST requests run the checkSubscription middleware.
But if I could declare on the top of the route file to run the middleware on all POST and PUT requests, that would save a lot of work and time.
Any kind of help would be highly appreciated. Thanks!
You can restrict the middleware to PUT and POST requests by evaluating the req.method inside:
function checkSubscription(req, res, next) {
if (req.method !== "PUT" && req.method !== "POST") return next();
// Rest of your middleware code
}
This keeps the rule "this middleware is only for PUT and POST" local to the middleware, no matter how often it is referenced in other statements like router.use and router.post.
But if I could declare on the top of the route file to run the middleware on all POST and PUT requests, that would save a lot of work and time.
You can just do something like this:
router.put("*", checkSubscription);
router.post("*", checkSubscription);
This will only call the checkSubscription() middleware for all PUT or POST requests that hit this router.
The "*" will match any path that goes through this router, but you could use any particular Express route pattern/regex there that you want if you want it to match more than one path, but not all paths.
As it sounds like you already know, you can also control route declaration ordering to give some routes a chance to handle the request before the middleware gets a shot to run.
Since Express runs middleware (including route handlers) in order, you can place the routes for which you don't want to run the middleware first, then the middleware, then the routes for which it does need to run:
router.get(...);
router.delete(...);
router.use(checkSubscription);
router.post(...);
router.put(...);
It does require some diligence with regards to app maintenance, because developers need to understand that the order in which the handlers are declared is relevant.
I am learning node.js and express.js in pursuit of becoming a full-stack javascript developer. Currently, I am learning express.js and the idea of middleware.
As I understand it, middleware is basically functions that have access to modify the request and response within the req-res cycle. Is this correct?
However, I am a bit gray in the idea of the next() function. I understand that it is designed to call the next middleware function in the flow of middleware functions, however, where does it come from. Where can I find it in the express.js package.
When you have, more middlewares, they will run in order, and each middleware will pass the result to next middleware. imagine you have a route that can be accessed only by authenticated users.
router.get("/products", adminController.getProducts);
this says, whenever a user makes a request to /products, run the controller for this route. However, if you want to show this route, only to authenticated users, you will write a custom middleware, check that a user is autenticated, is user authenticated you will let the adminController.getProducts otherwise you will show an error message. So you will be placing the middleware between.
router.get("/products", isAuth, adminController.getProducts);
Note that you could pass more than one middleware. (adminController.getProducts is also a middleware but I mean besides isAuth you could place as many as you want)
isAuth will be something like this:
export const isAuth = (req, res, next) => {
if (!req.session.isLoggedIn) {
return res.redirect("/login");
}
next();
};
Imagine you setup a session based project. When user logs in, express-session (you will get familiar) will add session.isLoggedIn=true to the req obj. So before user attemps to react "/products", you will be checking if req.session.isLoggedIn is true. If yes you will let the next middleware to run, if not you will be redirecting the user to "/login" route.
Interested in grabbing the user on every request so that I can have funtionality even on pages that don't have any stormpath functionality middleware.
Any issues with this? If user is logged in it returns the user in the request object, if the user is not logged in, it returns undefined. which is exactly what I want. Any 'gotchas' I'm missing? It 'seems' to work great.
app.get('*', stormpath.getUser, function(req, res, next) {
next()
});
That's fine, although your code won't cover all routes & http methods. It's probably easier to do this:
app.use(stormpath.getUser)
Since in express, all route handlers are "middleware", you can pass stormpath.getUser directly into the handler without the function calling next().
Also, matching all GET requests by using * will miss any POST, DELETE, PUT, etc requests. app.all will match all routes and all HTTP methods.
I have a MEAN application, and I'm handling authentication using passport. What I want to do is exactly what happens to the user on the passport, which can be accessed from the request like req.user. I have not found any solutions to reach that result. Can you give me any advice?
You can add properties to the request or response objects by creating a middleware and using it in your app. E.g.
// Defining middleware
function myMiddleware(req, res, next) {
req.myField = 12;
next();
}
// Using it in an app for all routes (you can replace * with any route you want)
app.use('*', myMiddleware)
Now all your request objects in your handlers will have myField property.
To add extra properties to the request and response object you need to extend the response and request interface.
index.d.ts files are used to provide typescript type information about a module that’s written in JavaScript.For express, the index.d.ts is present inside the #types/express folder inside the node_modules folder.
Use this link-
https://dev.to/kwabenberko/extend-express-s-request-object-with-typescript-declaration-merging-1nn5
I am building my first "real" MEAN application, and I am playing around with how to structure my REST api, which I would like to use as my backend.
I would like to know how to design the typical API methods in Express:
GET
POST
CREATE
UPDATE
I have made the following code, which solves the GET, UPDATE and DELETE. But how to implement POST? And is this decent practice?
Code:
app.get('/api/serials',function(req,res){
// get all serials code
});
app.get('/api/serials/:id',function(req,res){
// get by id code
});
app.get('/api/serials/:id/update',function(req,res){
// update code
});
app.get('/api/serials/:id/delete',function(req,res){
// delete code
});
You might be missing a fundamental concept here. A RESTful API responds to requests to the same URI differently, depending on the HTTP method.
// So it's NOT this:
app.get('/api/serials/:id/update', updateHandler);
app.get('/api/serials/:id/delete', deleteHandler);
// but rather `PUT` requests for updates
app.put('/api/serials/:id', updateHandler);
// and a `DELETE` requests for deletes
app.delete('/api/serials/:id', deleteHandler);
... where all requests that operate on an individual member of a resource collection are sent to the same URI.
Requests that operate on the resource collection are sent to the collection or base URI for the resource:
// the READ you already have right
app.get('/api/serials', indexHandler);
// but new resources should be created by POSTing to the collection URI
app.post('/api/serials', createHandler);