In general should routes be placed before or after middleware? - javascript

Oddly, when I moved my middleware in front of my routes, my routes stopped working. I got no error, on the client or the server.
My fetch() calls seemingly disappeared.
However when I put the routes before my middleware, the routes begin to work again.
I'm refactoring code and have no idea why this is happening.
// load middleware
const middleware = require(__dirname +'/middleware');
app.use(middleware.session.session);
...
// load routes
const routes = require(__dirname + '/routes');
app.use('/articles', routes.articles);
...

Routes and middleware should be placed in the order that you want them to be matched against the route and then to execute (if they match the incoming route). There is no absolute answer to which comes first as it really depends upon what you're trying to do. For example, you would put app.use(express.json()) before any route that wants to use a JSON formatted body. But, you would put the login page route handler BEFORE any middleware that checks to see if the user is authenticated (so that it can run for users that aren't yet authenticated).
If your code stops working when you put the middleware first, then there is probably something wrong with the implementation of the middleware. We can only help with that specific issue if you show us the actual code for that middleware. Perhaps you aren't calling next() to continue routing or you're sending a response in the middleware or there's a coding error in the middleware.

Related

node js express js request response circle

I am curious and really willing to learn and understand the whole concept behind the request and response circle of all backend
my question is I have a node js express framework
app is started
app.use('/api',router)
require('./routers/user')(router)
require('./routers/uretim')(router)
require('./routers/durus')(router)
require('./routers/rapor')(router)```
all my functions are called and executed and waiting for a request
since the order of this app is first use
app.use('/api',router)
then the router is called at this particular point router function has nothing attached to it,
so does it mean as we started our application we have created the routes with the executed functions below the app.use
main question
user enter ..../api
our back end was hit
what is the first process, or function that happens within our backend?
So the USE is used to load middleware, what you have is to use the router middleware on the /get url..
A better example of what is happening here is to define some action middleware on that url :
app.use("/api", (req, res, next) => {
// For example, a GET request to `/api` will print "GET /api"
console.log(`${req.method} ${req.url}`);
next();
});
When you start your server, if you hit your /api url, it will log the request info in the console and continue.
However the other URL's will not.. So you can tailor specific middleware for certain endpoints.
As for your routing itself, you will need to define the routes and their controller logic. Something like :
// HTTP GET Request Definition
app.get('/api',(req, res) => {
res.send("Hey, you hit API");
} );
This will happen after the middleware has been actioned.
Express

What parameters does next() take in Express

I am currently building an API thanks to Express.js, and I still can not believe how amazing it is. I figured out how to use middlewares, handling requests and responses, how to go to the next middleware ... But there is something that triggers me a lot, which is next().
I know what next() is, I just can't figure out what kind of parameters can next() take, and what they will do. At first I thought it was to pass data to the next middleware, turned out I was wrong, there is req.locals for this.
Can someone enlighten me on this ?
You have three choices for calling next():
1. Continue routing. If you just want to continue routing to the next route handler in the chain that matches this route, then you just call it with no parameters:
next();
This is most often used in middleware:
app.use((req, res, next) => {
// set an item in the session and then continue routing
req.session.xxx = "foo";
next();
});
2. Abort routing with an error to your centralized error handler. If you want to set an error and have routing skip to your generalized error handler, then you can pass an error:
next(new Error("timeout contacting database"));
This will then invoke your general error handling route and pass it that specific error where your general error handling code can decide what to do. This allows you to centralize your error handling response code in one place. Examples of using next(err) are here.
You can see the doc for generalized error handling in Express for examples on how that works.
3. Skip route handlers in this router, continue routing in other routers. If you want to skip all route handlers in the current router, but continue with any other routes that might be registered, then you can do this:
next('route');
From the doc:
You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke next('route') to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route.
If you repeatedly search for "next(" on this page of the doc, you will find lots of examples. There's an example of this usage here in the doc.
FYI, Express 5 may add some new uses for next() because it may return a promise that lets you know when routing is now completely done.

Require statements needed when something is already attached to a request in Node/Express?

Let's say I have an app in Node with the main elements of the application in a file at the root directory called app.js. Now let's say I have a route in ./routes/index.js.
If some of my middleware in app.js attaches handlers to the request, do I need to require the library that added that handler when handling the route in index.js?
I.e. in app.js:
var flash = require('connect-flash');
...
app.use(flash());
And in index.js:
var flash = require('connect-flash'); // ???
router.get('/', function(req, res, next) {
res.render('index', { message: req.flash('loginMessage') });
});
It appears to work without the require statement in index.js, but I want to make sure I'm understanding this conceptually. Once something is attached to the request, it stays with the request wherever it goes, right?
When you create an express application you create a "tree" so to speak, meaning that wherever you apply middleware any descending route will go through that function. So if we put the middleware at the top of our application all requests will go through that function. You only need to require the middleware wherever you are applying it to the application.
No, you don't. You only need require to get access to exported items from the module. If you don't need to access them (for instance, because something is already accessible as a property on req), you don't need the require.

app.use ("*") seems to be calling function multiple times

app.use("*", topUsers) is called multiple times..
topUsers is being called multiple times
function topUsers(req, res, next){
console.log("req.url", req.url)
findMostUsefullReviewsAggregate(6)
.then(function(aggregationResult){
// console.log("aggregationResult", aggregationResult)
// console.log("***aggregationResult::", aggregationResult)
return populateMostUseful(aggregationResult)
})
.then(function(populated){
console.log("<<<<<<<<<<<<<<<<<<TOPUSER CALLED >>>>>>>>>>>>")
// console.log("POPULATED: ", populated);
console.log(">>>populateMostUseful.length");
populated = populated.map(function(e){
e.momented = moment(e.createdAt.getTime()).fromNow();
return e;
})
req.session.mostUsefulReviews = populated;
// res.end()
})
.catch(function(err){
console.log("HEADERERR", err);
});
next();
}
( some info for later: main.ejs is for ("/"))
when I change it to app.get("/", topUsers) and go to "/"it is only called once (which is what I want).
the console.log for req.url shows "/" for all 3
In my main.ejs I include a header.ejs. I thought that might be a problem. Maybe the request to the header for the include was a problem but I don't think so.
Quick question : If I do app.get("/") would that work on all subroutes like /users/idofuser? I think If I do that the function doesn't get called.
I think app.get("*") also gives me the same problem with the multiple calls.
Edit: when I put next in the .then() it still gets called multiple times.
my real goal it to have something happen on all routes. I already have routes set up. I don't want to go to each route and do something like app.get("/", onemiddleware, topUsers, ). I don't want to put topUSers on each one physically. Do I have to.
If you are doing this from a browser loading a web page, the browser is probably requesting multiple resources from the website.
For starters, it often requests the favicon and if there are any other resources in the web page (other scripts, stylesheets, images, etc...) each of those will be a separate request to your web page. You can see exactly what URL is being requested by logging req.url for each request. From a single page load, there should be no reason you would get three requests for /, but you very well could get a request for / follow by other requests for some other resource (and consequently some other URL) from the same server.
Show us the web page you are loading and we can better point out what's going on.
If what you're really trying to do is to share a middleware on a set of routes, then you can create a router, put the middleware on the router with router.use(), define all the routes that you want to have that middleware on that specific router and then hook the router into your app. This will execute the middleware only for routes that match that router and you only have to specify the middleware once for the router and all routes defined on that router will use that middleware. Other routes defined directly on the app object or on other routers will not use the middleware. You will have to define the router as some unique path root or wildcard that helps express know which routes should be passed into your router. We'd have to see the whole universe of paths you plan to use that both do and don't use that middleware for us to know more specifically what to suggest.

NodeJs Express Router Error

I'm rewording this since I have figured out what the problem is, but I cant understand how its happening or how to resolve it.
Basically, in all of my routes I have to places where I am adding a DELETE route. The first is as follows
app.route('/bi/clubs/:id')
.post(authentication,clubController.getAll)
.delete(authentication,clubController.deleteClub);
The second location is
app.route('/bi/clubs/members')
.post(authentication,memController.getAll)
.delete(authentication,memController.deleteMember);
Whenever I call DELETE on the '/bi/clubs/members', express is actually routing that to '/bi/clubs/:id'. I have actually gone through and traced that this is occurring.
I can validate that I am not adding the route anywhere else in the app, and if I comment out the DELETE route on '/bi/clubs/id', then the second DELETE route will route properly. If I don't comment it out, the call to DELETE '/bi/clubs/members' will route to '/bi/clubs/:id'.
The order in which I am setting the routes is just as above.
Any help would be much appreciated.
Express is matching your route /bi/clubs/membersas /bi/clubs/:id. When a request is made to an Express app your app will start at the top of your routes and middleware and work its way down to the end hitting all the routes that it matches.
When you tell Express to match the route /bi/clubs/:id, all you are telling it is match bi, then clubs and then a dynamic value that you are referring to as id. Although you are probably looking for id to be a number or a MongoDB ID, Express doesn't know the difference, so technically the string members matches as a dynamic value. Just not the one you want.
If you console.log the value of id it should be members. Your static routes need to be registered before your dynamic routes.
If you have any questions or would like an example please let me know.

Categories