Skip to content

Error: Can't set headers after they are sent. CORS #2448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
benishak opened this issue Aug 4, 2016 · 28 comments
Closed

Error: Can't set headers after they are sent. CORS #2448

benishak opened this issue Aug 4, 2016 · 28 comments

Comments

@benishak
Copy link
Contributor

benishak commented Aug 4, 2016

Env

Parse Server 2.2.17
AWS CentOS NGINX

Problem

I'm getting this error in the console

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
    at applyHeaders (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:146:15)
    at applyHeaders (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:142:11)
    at applyHeaders (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:142:11)
    at cors (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:177:7)
    at /home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:228:17
    at originCallback (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:217:15)
    at /home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:222:13
    at optionsCallback (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:203:9)
    at Object.handle (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:208:7)

after downgrading to version 2.2.16. The error goes away!

Reproduce

Upgrade to 2.2.17

@benishak
Copy link
Contributor Author

benishak commented Aug 4, 2016

expressjs/express#751

@TylerBrock
Copy link
Contributor

Can you provide any additional information on what triggers this use error? Is there a particular endpoint you hit or action that you are taking when it happens?

@neophob
Copy link
Contributor

neophob commented Aug 4, 2016

I also see this error on v2.2.17:

at Layer.handle [as handle_request] (/bundle/node_modules/express/lib/router/layer.js:95:5) 
at jsonParser (/bundle/node_modules/parse-server/node_modules/body-parser/lib/types/json.js:94:7) 
at next (/bundle/node_modules/express/lib/router/index.js:271:10) 
at Function.process_params (/bundle/node_modules/express/lib/router/index.js:330:12) 
at /bundle/node_modules/express/lib/router/index.js:280:7 
at trim_prefix (/bundle/node_modules/express/lib/router/index.js:312:13) 
at Layer.handle [as handle_request] (/bundle/node_modules/express/lib/router/layer.js:95:5) 
at allowCrossDomain (/bundle/index.js:439:9) 
at ServerResponse.header (/bundle/node_modules/express/lib/response.js:719:10) 
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11) 
Error: Can't set headers after they are sent.

It happens if I run cloud code, I couldn't identify exactly where it is but it's related to the errorhandler in the cloud code

@flovilmart
Copy link
Contributor

The problem is not from parse server itself but how the express routes are configured. Some of your middlewares are run after parse has processed it's requests. Please check the order of your middlewares and also, consider excluding the parse route.

Another option may be:

// do not mount any middleware on the main app
let app = express()
// mount your middlewares only in myApp
app.use(myApp)
app.use('/parse', parseAPI)

Again it depends of the middlewares you use, and how they are designed.

Calling next() is part of express best practices, so I don't think we'look remove it.

@neophob
Copy link
Contributor

neophob commented Aug 4, 2016

thanks @flovilmart - I also assume this is more an error on my/our end than a parse error, I'll investigate. however I never saw those errors before v2.2.13

@flovilmart
Copy link
Contributor

That's normal that it didn't appear before as we added next() calls after error/responses so additionnal loggers/handlers can be called after parse-server responded

@blacha
Copy link
Contributor

blacha commented Aug 5, 2016

I have been following this and #2362, I have not been able to reproduce any Header error unless I do something wrong inside the express side of things. E.g binding the parse app twice, or sending res.headers() twice.

As I stated in the other issue the common places to look is your app.use and app.get/post

The order is very important to app.use

app.use(function(req, res, next) {
    console.log('beforeParse');
    next();
});

app.use('/parse', ParseInstance);

app.use(function(req, res, next) {
    console.log('afterParse');
    next();
});

@flovilmart
Copy link
Contributor

See #2362

@benishak
Copy link
Contributor Author

benishak commented Aug 9, 2016

I don't think that this is the issue. I disabled cloud code, Open Parse Dashboard, voila! for each class in the schema I get the same error repeated!

 method=GET, url=/classes/Any, connection=upgrade, host=api-dev.[].com, content-length=293, user-agent=node-XMLHttpRequest, Parse/js1.9.0 (NodeJS 4.4.2), accept=*/*, content-type=text/plain, __type=Date, iso=2016-08-09T11:55:01.122Z
verbose: RESPONSE from [GET] /classes/Any: {
  "response": {
    "results": []
  }
} results=[]
Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
    at applyHeaders (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:146:15)
    at applyHeaders (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:142:11)
    at applyHeaders (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:142:11)
    at cors (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:177:7)
    at /home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:228:17
    at originCallback (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:217:15)
    at /home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:222:13
    at optionsCallback (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:203:9)
    at Object.handle (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:208:7)

So I don't think this is my cloud code issue

and here is my server init

var api = new new ParseServer({ ... });

var app = express();
app.use(cors()); // Enable CORS
app.options('*', cors()); // Enable CORS-Pre-Flight
app.use('/', api);

app.get('/', function(req, res) {
  res.status(200).send('This is a sovereign territory!');
});

app.all('*', cors(), function(req, res, next){
  res.jsonp({msg: 'This is CORS-enabled for all origins!'});
});

app.listen(config.APP.PORT, function() {
    console.log('parse-server running on port ' + config.APP.PORT + '.');
    if (config.DEBUG){
        console.log = function(){}
    }
});

@flovilmart
Copy link
Contributor

This is likely app.all('*', cors(), ... try commenting that line?

@benishak
Copy link
Contributor Author

benishak commented Aug 9, 2016

yes I tried to comment that line and also
app.options('*', cors()); // Enable CORS-Pre-Flight

and also

app.get('/', function(req, res) {
  res.status(200).send('This is a sovereign territory!');
});

as I thought maybe it cause the problem because I'm mounting in '/'

but still see the error

@flovilmart
Copy link
Contributor

Given the stacktrace this is because your cors middleware is run AFTER parse-sever. But not inside parse-server

@benishak
Copy link
Contributor Author

benishak commented Aug 9, 2016

what do you mean ?

my index.js looks like this now

// init the App
var app = express();
app.use(cors()); // Enable CORS
//app.options('*', cors()); // Enable CORS-Pre-Flight

// Parse Initialisation
var api = new ParseServer({
        ......
});

app.use(config.PARSE.PARSE_MOUNT, api);

//app.all('*', cors(), function(req, res, next){
//  res.jsonp({msg: 'This is CORS-enabled for all origins!'});
//});

app.get('/', function(req, res) {
  res.status(200).send('This is a sovereign territory!');
});

app.listen(config.APP.PORT, function() {
    console.log('parse-server running on port ' + config.APP.PORT + '.');
    if (config.DEBUG){
        console.log = function(){}
    }
});

I still see the error

@flovilmart
Copy link
Contributor

I mean

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
    at applyHeaders (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:146:15)
    at applyHeaders (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:142:11)
    at applyHeaders (/home/centos/apps/parse-server-dev/source/node_modules/cors/lib/index.js:142:11)
``` 

THAT is not generated by parse-serve but by the CORS middleware here: https://github.com/expressjs/cors/blob/master/lib/index.js#L177

As for why, I'm not sure...

@benishak
Copy link
Contributor Author

benishak commented Aug 9, 2016

I also remove app.use(cors()); // Enable CORS but still see the error

@flovilmart
Copy link
Contributor

What error? we don't have the cors module in parse-server, are you sure it's exactly the same stack trace?

@benishak
Copy link
Contributor Author

benishak commented Aug 9, 2016

here is the other error coming from express

verbose: RESPONSE from [GET] /classes/Something: {
  "response": {
    "results": [],
    "count": 7
  }
} results=[], count=7
Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
    at /home/centos/apps/parse-server-dev/source/node_modules/express/lib/application.js:153:9
    at /home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:137:5
    at /home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:250:10
    at next (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:160:14)
    at next (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:176:38)
    at Immediate.<anonymous> (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/application.js:190:9)
    at Immediate.<anonymous> (/home/centos/apps/parse-server-dev/source/node_modules/parse-server/node_modules/express/lib/router/index.js:618:15)
    at Immediate.immediate._onImmediate (timers.js:435:18)
    at processImmediate [as _immediateCallback] (timers.js:383:17)

this is even after removing CORS completely

@flovilmart
Copy link
Contributor

So you you notice this is not the same stack trace therefore the same error?
Also, the failing module is not the express module from parse-server but the express module from your project.

I'm not sure at that point why your express module would spit those errors. I tested with parse-server-example and didn't get that output either. What version of express are you running in your main package?

@benishak
Copy link
Contributor Author

benishak commented Aug 9, 2016

Thanks.
I'm using latest express of 4.2.x

    at Immediate.<anonymous> (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/application.js:190:9)
    at Immediate.<anonymous> (/home/centos/apps/parse-server-dev/source/node_modules/parse-server/node_modules/express/lib/router/index.js:618:15) // <<< ----- express from parse server

@flovilmart
Copy link
Contributor

use express 4.14.0 https://github.com/ParsePlatform/parse-server/blob/master/package.json#L28 as parse-server uses, it's untested with 4.2 which by the way is more than 2 years old... https://github.com/expressjs/express/tree/4.2.0 .

@benishak
Copy link
Contributor Author

benishak commented Aug 9, 2016

Thanks a lot! this saved my life :) I also had to remove app.all('*',cors ...) after upgrading to express 4.14.x

@oli107
Copy link

oli107 commented Aug 9, 2016

Wow, I've been watching this thread for ages stuck with the same issue, and it turns out the issue all along was the express version. I had based my original project off of parse-server-example which prior to March 16th had express ^4.2.x in the package.json. This was updated after that date to ^4.11.x. I had to make no code changes except change to 4.14.0 and it all works now.
Thanks.

@benishak
Copy link
Contributor Author

benishak commented Sep 2, 2016

It stills happen although using express 4.14.0 using node 4.5

at Layer.handle_error (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/layer.js:71:5)
2|S [d |     at trim_prefix (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:310:13)
2|S [d |     at /home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:280:7
2|S [d |     at Function.process_params (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:330:12)
2|S [d |     at next (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:271:10)

this happen when afterSave/BeforeSave trigger.

with Node 6.4.0

2| [d | Error: Can't set headers after they are sent.
2| [d |     at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
2| [d |     at ServerResponse.header (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/response.js:719:10)
2| [d |     at ServerResponse.send (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/response.js:164:12)
2| [d |     at ServerResponse.json (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/response.js:250:15)
2| [d |     at handleParseErrors (/home/centos/apps/parse-server-dev/source/node_modules/parse-server/lib/middlewares.js:275:9)
2| [d |     at Layer.handle_error (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/layer.js:71:5)
2| [d |     at trim_prefix (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:310:13)
2| [d |     at /home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:280:7
2| [d |     at Function.process_params (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:330:12)
2| [d |     at next (/home/centos/apps/parse-server-dev/source/node_modules/express/lib/router/index.js:271:10)

In this function!

handleParseErrors (/home/centos/apps/parse-server-dev/source/node_modules/parse-server/lib/middlewares.js:275:9)

After I comment that line, it works

@sunshineo
Copy link
Contributor

@benishak Can you make a pull request that delete that line?

@sunshineo
Copy link
Contributor

This is how I solved it:

app.use('/parse', parse);
app.use('/parse', function(req, res, next) {
    console.log('afterParse stop next()');
    // next();
});

I have no idea why after parse-server handled the request it want to call "next()". Does it have anything to do with Cloud code? If that is the case, I guess parse-server is meant to be stand alone. It is not mean to be installed onto your node server.

@flovilmart
Copy link
Contributor

There is already an open PR to remove the next() calls

@sunshineo
Copy link
Contributor

@flovilmart Which PR? Do you have a link?

@flovilmart
Copy link
Contributor

#2634

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants