node express - does middle way order matter? Getting error - node.js

My code below gives me an error: Error: Can't set headers after they are sent.
If I put app.use('/special/... before app.use('/' ... it doesn't give me an error-
1. As I understand when using app.use the order does matter because the program doesn't look like when I use app.get for example, for anything after '/ or '/special/ so why am I getting an error?
Also when I put app.use('/special/' first I am still not seeing "first" and second" but only the first one - even though I use next..
Can someone explain?
Thanks!!
What does it mean?
var express=require ('express');
var app=express();
app.use('/',function(req,res,next){
res.send('first');
next();
});
app.use('/special/',function(req,res,next){
res.send('second');
next();
});
app.listen(3000, function(){
console.log('Server listening');
});

In your case it's nothing about order, but you can't invoke res.send('some_result') twice when one resource required,you can check this in detail Stackoverflow.
also, when you use app.use() to add middleware to your system,Express use regex to match your request url,so when you have the code below:
app.use('/',function(req,res,next){
res.send('first');
next();
});
all the request(regardless of HTTP verb) start with '/' will meet the requirement.
finally when request below:
POST /special
both of the middlewares will be invoked.

Problem
The two routes
app.use('/',function(req,res,next){
res.send('first');
next();
});
app.use('/special/',function(req,res,next){
res.send('second');
next();
});
both match the url /special. That's why both of them are executed by node. Since res.send() in the first route closes the http response from the server, the res.send() in the second router throws an error since it tries to set a header (e. g. Content-length) while output from the first route has already been sent.
Solution
Always put the more specific route first so that it is reached at all. If the first route you define matches /, no other route would ever be called.
Also, do not call next() if you want to call res.send() in routes. Best practice: next() should only be invoked in middlewares which do not send a response.
A possible solution looks like this:
var express=require ('express');
var app=express();
app.use('/special/',function(req,res){
res.send('second');
});
app.use('/',function(req,res){
res.send('first');
});
app.listen(3000, function(){
console.log('Server listening');
});

Related

what happens in app.use(express.static) and app.use(require("cors")()) and what middlewares are

I started with express a few days ago.
I dont really understand what happens in:
const express = require("express")
const app = express()
app.use(express.static(path.join(), "public"))
app.use(require("cors")())
app.listen(3000, () => console.log("running"))
the first example worked for me but i dont really understand it.
and basiclly i dont understand what happens in app.use() and what middlewares are..
someone can help me pls?
i read many blogs and I didnt got it :(
The Background
There are several parts to explaining this. First, off app.use() expects a middleware function to be passed to it. That would be a function with a signature like this:
app.use(function(req, res, next) {
console.log(req.path); // log incoming request path
next(); // continue routing to other handlers
});
It accepts other combinations of parameters, including an initial path and you can pass multiple middleware functions too and it will chain them together, but the basics of your question is about a single middleware function as shown above. That middleware function gets three arguments req - the incoming request object, res - the outgoing response objet and next - a function to call if you want to continue routing or report an error.
The job of one of these middleware function is to use the input in the req object to do some kind of processing of that input (depending upon what the purpose of the middleware function is) and then do one of three things:
Send a response using something like res.send() in which case the request has been handled and a response has been sent and no further routing will be done.
Continue routing to further request handlers in the chain by calling next().
Abort routing and go to the Express error handler by calling next(err).
The express.static() Middleware
So, that's what is expected of a function passed to app.use(). Now, let's look at the two examples you ask about. Let's start with express.static():
app.use(express.static(path.join(), "public"))
First, this isn't proper use of express.static(). I'm not sure exactly what you intended, but I will assume you meant something like this:
app.use(express.static(path.join(__dirname, "public")));
In this case, express.static() takes some configuration information which is the resulting path from calling path.join(__dirname, "public") and uses that to create a custom middleware function. So, calling express.static(path.join(__dirname, "public")) returns a function that expects to be called with the three middleware arguments we previously discussed. It is logically identical to this:
const publicPath = path.join(__dirname, "public");
const myStaticMiddleware = express.static(publicPath);
app.use(myStaticMiddleware);
which is logically equivalent to this:
const publicPath = path.join(__dirname, "public");
const myStaticMiddleware = express.static(publicPath);
app.use(function(req, res, next) {
myStaticMiddleware(req, res, next);
});
Where the code has been broken down into separate steps just so you can see each step separately.
And, in case you didn't already know, the point of the express.static() middleware is to serve static files from a designated directory if an incoming request matches a filename in that designated directory exactly and has an appropriate file type.
The cors Middleware
For your second example:
app.use(require("cors")())
Let's again break that down to the individual steps:
const cors = require("cors"); // load cors module
const corsMiddleware = cors(); // create cors middleware function
app.use(corsMiddleware); // register middleware with Express server
Which can be expanded to:
const cors = require("cors");
const corsMiddleware = cors();
app.use(function(req, res, next) {
corsMiddleware(req, res, next);
});
Just to show you that corsMiddleware is called with these three arguments.
The purpose of this particular middleware is to help configure a response to this request so that cross origin requests will be accepted.

How Express recorgonizes middlewares?

I'm novice in Express and a little bit confused about how it handles middlewares? So basically I have two middlewares which looks like:
app.use(require('_/app/middlewares/errors/404'))
app.use(require('_/app/middlewares/errors/500'))
404
var log = require('_/log')
module.exports = function (req, res, next) {
log.warn('page not found', req.url)
res.status(404).render('errors/404')
}
500
var log = require('_/log')
module.exports = function (er, req, res, next) {
log.error(er.message)
res.locals.error = er
res.status(500).render('errors/500')
}
So now I want to add my custom middleware app.use(require('_/app/middleware/shareLocals')) which looks like:
module.exports = function (req, res, next) {
res.locals.base_url = req.protocol + '://' + req.get('host');
next();
}
The main problem is that now when I try to use base_url I get 404 error...
So how Express understands what middleware do? That is between my middleware and 404 are no visual differences:
it receives same params
it doesn’t have any if's in it, just throws 404 error
Appears the feeling the middlewares in Express are made for errors (when excepts err as first param) and for 404 (when there is no first err)...
P.S.
Is there any difference defining middlewares before or after routes?
P.S. Is there any difference defining middlewares before or after routes?
Yes.
The order in which you register your middlewares (and routes) have a lot to say.
Image express as a giant list. Starting at the first element in the list, you have the first middleware OR route you have defined, next is the second, etc.
When express gets a request, it appears to be matching your route/name of route/middleware, and if it's a hit, it executes the middleware/route and potentially waits for a "next()" call.
So if you have a route "/test" it will only be executed if you have a request matching "/test". routes with different names obviously wont get triggered. middlewares can also have names: app.use("/test", middlewareA). This will also only trigger if "/test" is requested. The way you do it, all requests (within the routes namespace) will be triggered app.use(middlewareA). It's like a wildcard.
Now, to the implications of things being ordered:
Your 404 middleware should only be used AFTER all routes have been defined. that way, when the list reached the 404 middleware, no routes have actually been found.
returning/sending result/not calling next() at the end of a middleware will all potentially create problems in your flow. I wont go into details about this, but be aware of it.
I am guessing your own middleware is added after the 404 middleware. That is probably the problem. If not, you should surrender more of your code so we can take a better look. But remember, order is everything :)

404 when accessing new route

I'm trying to add a new route (/profile) to my NodeJS Express web application. I've modified my app.js file like this:
var routes = require('./routes/index');
var profile = require('./routes/profile');
app.use('/', routes);
app.use('/profile', profile);
The '/' index path works fine, my issue is with '/profile'. Whenever I try to access it, I get a 404. This is profile.js:
var express = require('express');
var router = express.Router();
router.get('/profile', function(req, res) {
var username = req.session.username;
if(username) {
res.render('profile');
} else {
res.redirect('/login');
}
});
module.exports = router;
I don't understand what I'm doing wrong because in the example express application that is generated, '/users' works fine. I basically copied that format, but it's throwing a 404. Any ideas?
In my profile.js, I had to change my GET request path to this:
router.get('/', function(req, res) {
//code
});
Otherwise, the router would be looking for /profile/profile. When I change it to /, it's just looking for the root of `/profile', or at least that's how I understand it.
To understand what you are doing wrong you should know that Node.js uses middleware functions to route your requests. To simplify you can think about it as a chain of functions.
Middleware is like a plumbing pipe, requests start at the first middleware you define and work their way “down” the middleware stack processing for each path they match.
So with the following statement you added a middleware function to handle any request starting with the root path /profile, and it is a common pattern in Node to use the use method to define the root paths.
app.use('/profile', profile);
The use method is doing part of the routing in your scenario and the statement above will match any route starting with that path, including /profile/all or /profile/12 or even /profile/go/deeper/inside.
However, you want to narrow down that routing to something more specific, so that is why you pass a router middleware function (profile in your case) to match more specific routes instead of all routes starting with /profile.
The profile middleware function is actually the next step in the chain of functions to execute, and it will start from the root path specified in the use statement, which is the reason why you need to start again with / and not with /profile. If you wanted to match a profile by ID you would do:
router.get('/:id', ...)
Which would be concatenated with the base URL (from the /use statement) and would match a request like /profile/2 or /profile/abc.

Something is wrong with domains in NodeJS

I have this simple code. This must show me my error object ({error:'error'}) upon each request. But it shows only "[Object object]".
And moreover - debugger never stops in the error handler function.
What is going on?
var domain = require('domain');
var express = require('express');
var server = express();
server.get('/', function(req, res)
{
var d = domain.create();
d.on('error', function(e)
{
debugger;
console.log(JSON.stringify(e));
});
d.run(function()
{
throw {error:'error'};
res.send('ok');
});
});
server.listen(8080);
The problem is that domains catch the error all the way at the bottom of the call stack, and since express has its own error handling code, the error gets caught by express before reaching the domain. Similar issue here: Node.js - Domain per Express request, inside another domain
I don't see any particularly good reason it should be this way, but that's how the code seems to work [1] (source here: https://github.com/joyent/node/blob/master/lib/domain.js). Possible workarounds are to surround the d.run() call with your own try/catch, or to do something like
d.run(process.nextTick(function() {
// do stuff
}));
[1] The way domains work is that they basically hook into all of the "asynchronous" callbacks and add some information that records who initiated the asynchronous operation. I don't know why they don't also try/catch on the initial synchronous block.

NodeJS Express wildcard route executed several times

Consider the following code snippet:
var count = 0;
function a(req, res, next){
count++;
console.log(count);
next();
};
app.get('*', a);
app.get("/", routes.index);
app.get("/foo", routes.foo);
Function a() will be executed for every route defined, in this case 2, per http request. The count variable is just to illustrate. So if I had 100 routes defined, a() would be executed 100 times per request to the site. Is this the expected behavior, or am I doing something wrong? Thanks!
You should check out the network traffic or log the request in your a function. Most likely the second request you are seeing is for favicon.ico. Each route when only be called once per matching request.

Resources