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.
Related
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.
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
I already searched for a good while on the Internet and even checked all suggested questions here, but I found nothing.
Basically, I'm using vue-router to load views when the user clicks on them (without prefetching, just lazy-loading), using a function that imports the Vue view/component. To better visualize, I made a barebone example of what I'm doing:
const router = new VueRouter({
routes: [
...
{
path: "/a_page",
component: function() {
return import("./views/A_Page.vue");
}
}
]
});
I'm using Express in the backend to protect certain routes, because protecting it in the Frontend is wasted effort, since the user could bypass the 'protection' easily, if he wants to. Also all views have their own splitted .js file (using "webpackChunkName") and Express needs a Bearer Authentication Token header for every API call OR .js file requested. This works great with Axios (responsible for fetching API data) where you can manually define a header, but vue-router hasn't this option, and since it doesn't send the Authorization header, it doesn't authenticate, Express blocks the file with a 403 and vue-router fails to import the file.
Is there any way to send the Authorization header with the import (which is basically just a GET request)?
Thanks in advance.
If someone thinks I'm approaching the problem in a wrong way, feel free to comment and suggest another way.
EDIT: The suggested duplicate question was given too little attention and the only solution given (which is basically split in 2) doesn't work with the current webpack anymore; onload(event) and onerror(event) get undefined.
You could use a router guard instead of protecting with basic auth.
I use this method, along with lazy loaded routes. If the auth fails you can redirect the user to a login page.
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
If (auth) { // get value of cookie etc for a jwt token or similar auth method
next() // proceed
}
else {
next(false) // cancel navigation
// or
next(“/login-url”) // redirect you login url
}
})
Additionally, you could use an axios method to auth on each route change.
If you want to send up the Authorization header (which doesn't seem to be an easy task, given that no one knows how to go about it...) I think you could override webpack's jsonp function that it uses to load the chunks in splitChunks...
Here's the docs for the webpack function that loads the chunks
You'll override your webpack config with your modified chunk loading function and then tie that into your vue.config.js like so...
// vue.config.js
module.exports = {
configureWebpack: require('./webpack.config.js')
}
All this being said, I would suggest protecting your frontend assets much earlier than when you need to be loading your split chunks and not requiring the Authorization header to serve your static assets.
Sometimes you can do this at the network layer (load balancer, etc) depending on your use-case. Other times using a server-based approach, like rendering your app w/ Nuxt, will be what you want.
If I'm understanding correctly (feel free to correct me), would you be able to do an auth call with axios prior to the actual routing, or perhaps upon the routing using a mounted call? Especially if there is no valid authentication you can then either redirect to a login page or re-route to an error page.
Feel free to let me know if I'm misunderstanding.
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.
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.