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
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 using a res.redirect('page.ejs'); and on my browser I get the message:
Cannot GET /page.ejs
I have not declared this in my routes file in the style of :
app.get('/page', function(req, res) {
res.render('page.ejs');
});
Should this be included in order for the res.redirect() to work?
When I do not use res.redirect() but res.render(), even if I have not the app.get() code, it still works.
so to understand this, let's look at what each of these methods do.
res.redirect('page.ejs');
// or, more correctly, you're redirecting to an *endpoint*
// (not a page. the endpoint will render a *page*) so it should be:
res.redirect('/page');
this will tell express to redirect your request to the GET /page.ejs endpoint. An endpoint is the express method you described above:
app.get('/page', function(req, res) {
res.render('page.ejs');
});
since you don't have that endpoint defined it will not work. If you do have it defined, it will execute the function, and the res.render('page.ejs') line will run, which will return the page.ejs file. You could return whatever you want though, it can be someOtherPage.ejs or you can even return json res.json({ message: 'hi' });
res.render('page.ejs');
this will just respond to the client (the front-end / js / whatever you want to call it) with the page.ejs template, it doesn't need to know whether the other endpoint is present or not, it's returning the page.ejs template itself.
so then, it's really up to you what you want to use depending on the scenario. Sometimes, one endpoint can't handle the request so it defers the request to another endpoint, which theoretically, knows how to handle the request. In that case redirect is used.
hope that makes sense and clarifies your confusion
(I'm not an expert on the inner-workings of express, but this is a high-level idea of what it's doing)
You should do res.redirect('/page')
In my server.js file, where I may have many lines of code that use app.use, do these lines app.use execute every time a path is hit? I am a little confused on how this works when using the express router. If I have something like
var example1 = require('./js/exampleRoutes.js)
var example2 = require('./js/example2Routes.js)
app.use(express.static(process.cwd() + '/public'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(methodOverride("_method"));
app.use(example1, example2);
app.listen(PORT);
Do all four lines of app.use execute everytime a path is hit, and depending on the path hit, it will redirect the program to either example1 routes or example2 routes?
exampleRoutes.js
router.get('/', function(req, res){
....
});
example2Routes.js
router.post('/create', function(req, res){
....
});
Does express app.use execute every time a path is heard on server.js
It depends upon whether you're using a path with any of your app.use() statements and it depends upon whether all the app.use() statements pass control onto the next handler or whether some of them purposely terminate the chain and handle the final response themselves.
All app.use() statements are registered as middleware handlers for all requests that hit that app object. If it has a specific path on it, then it will only be called if it matches that path. If it does not have a path (as in your examples), then it will be considered for every request.
When a given middleware handler is called, it is passed three arguments as in this example from the Express doc:
app.use(function (req, res, next) {
console.log('Time: %d', Date.now());
next();
});
Note, that last argument next. When a middleware function gets called, it has three main choices for how it's going to work:
It can do something and then let the request continue on to other handlers.
It can do something and then trigger an error (for example authentication failed or a require session cookie is missing).
It can do something and then send the final response (res.send(xxxx)) and not pass control on to other handlers.
The mechanism for passing control on to other handlers is by calling next() when you are done with your processing and ready for other handlers to get their crack at this request. If each middleware handler calls next() for each request they see, then ALL the app.use() handlers will get called for every single request. In the example above from the Express doc, you can see that this is a very simple middleware handler. All it does is log the time of the request and then it calls next() to pass control onto the next handler in the chain.
If one of the middleware handler does not call next(), then for that request, none of the handlers that come after it in the chain will get called for that request.
On a separate note, you can limit middleware to certain url paths only. Rather than calling
app.use(example1)
you can include a path as an argument such as:
app.use('/api', example1);
Then, this middleware will only be called for paths that start with /api.
Or, you can similarly use Routers to create branches of middleware. For example, if you have some middleware handlers that you only want to be called for requests that start with /api, then you can create a router for the /api prefix on the URL and attach the middleware handlers to that router instead of to the app object and then the middleware handlers on that router will only be called for requests that start with /api and are thus directed to that router.
// create api router
var router = express.Router();
// register middleware that is called only when requests go through this router
router.use(example1);
// register normal get handler
router.get('/whatever', function(req, res) {...});
// hook api router into the app
app.use('/api', router);
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.
Having this simple express app example:
var express = require('express')
var app = express()
app.use(express.static(__dirname+'/public'))
app.get('/', function(request,response) {
response.send("This wont matter if we got an index.hml after all")
})
app.listen(2311, function() {
console.log("app escuchando en Maricela DDMM")
})
And at /public I got an index.html.
When I get rid of such html the string in the send() method will be sent, received and rendered at browser.
What does actually happen with the response.send() string talking about the HTTP response, as the HTML is which is send and so rendered at browser?
Express goes through the chain of middleware in the order in which it was added. You have added express.static as the first middleware, so it will be ran first.
In the event express.static cannot find a file, it calls next(), allowing the next bit of middleware to run. This is your handler set up with app.get('/' //..., which sends the data as you have told it to.
I think it basically sets up the header information based on the parameter in send and then send the http response