0

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');
});
javascript2016
  • 973
  • 3
  • 17
  • 41

2 Answers2

1

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.

Community
  • 1
  • 1
TommyLike
  • 1,010
  • 11
  • 20
1

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');
});
Steffen Langer
  • 1,141
  • 1
  • 12
  • 16
  • Okay thanks. I actually believed that order doesn't matter when it comes to app.use and only matters in ..get,...post etc. Another question-I believed I need to call next whenever I use app.use, because if I don't, it will stop executing other functions after the first app.use?! Why else do I need next()?Thanks!! – javascript2016 Jun 30 '16 at 01:08
  • @javascript2016 when you use **app.use** to mount resource ,**next()** is not required – TommyLike Jun 30 '16 at 05:50
  • app.use() mounts a middleware. If you would like other middlewares to be executed after the one in question, you should call next(). That may be the case if you try to authenticate the user on each request. On the other hand, routers typically send an answer and do not need any other middleware to be executed. – Steffen Langer Jun 30 '16 at 06:09
  • so when I have two app.use middleware functions and do not use next(), its still gonna get to the second middleware function? Also, when I run your code, I only get first logged, not "second" – javascript2016 Jun 30 '16 at 19:59