question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

"Cannot set headers..." error happening only on one specific kind of request

See original GitHub issue

I’m using Node 10.1.0, and node-static v0.7.2. The error stack in my logs:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:471:11)
    at ServerResponse.writeHead (_http_server.js:231:21)
    at Server.finish (/tmp/site/node_modules/node-static/lib/node-static.js:125:17)
    at finish (/tmp/site/node_modules/node-static/lib/node-static.js:170:14)
    at /tmp/site/node_modules/node-static/lib/node-static.js:337:13
    at streamFile (/tmp/site/node_modules/node-static/lib/node-static.js:382:13)
    at ReadStream.<anonymous> (/tmp/site/node_modules/node-static/lib/node-static.js:375:17)
    at ReadStream.emit (events.js:182:13)
    at fs.close (fs.js:2161:14)
    at FSReqWrap.oncomplete (fs.js:152:20)

I’m experiencing this persistent error every single time a specific kind of request comes in – but only for that, all other requests are fine – which appears to be a request from a Slackbot. Here are the request headers from the specific request:

{"x-forwarded-host":"my.domain.tld","x-forwarded-proto":"https","x-forwarded-port":"443","x-forwarded-for":"::ffff:52.71.192.87","if-modified-since":"Mon, 17 Oct 2016 23:58:19 GMT","accept-encoding":"gzip,deflate","accept":"*/*","user-agent":"Slackbot 1.0 (+https://api.slack.com/robots)","host":"my.domain.tld","connection":"close"}

Here’s my code:

"use strict";

var path = require("path");
var http = require("http");
var httpServer = http.createServer(handleRequest);
var nodeStatic = require("node-static");
var staticServer = new nodeStatic.Server(path.join(__dirname,"static"),{
        serverInfo: "my-server",
        cache: 86400,
        gzip: true,
});

const HSTS = `max-age=${1E9}; includeSubdomains`;

httpServer.listen(8003);

// *********************

function handleRequest(req,res) {
        // unconditional, permanent HTTPS redirect
        if (req.headers["x-forwarded-proto"] !== "https") {
                res.writeHead(301,{
                        "Strict-Transport-Security": HSTS,
                        "Cache-Control": "public, max-age=31536000",
                        Expires: new Date(Date.now() + 31536000000).toUTCString(),
                        Location: `https://${req.headers["host"]}${req.url}`
                });
                res.end();
        }
        else if (["GET","HEAD"].includes(req.method)) {
                req.addListener("end",function requestEnd(){
                        req.removeListener("end",requestEnd);
                        res.setHeader("Strict-Transport-Security",HSTS);
                        staticServer.serve(req,res);
                }).resume();
        }
        else {
                res.writeHead(404,{ "Strict-Transport-Security": HSTS });
                res.end();
        }
}

As you can see, my server is running on localhost:8003 – I have a public server on 80/443 that proxies the requests after doing SSL certificate handling, etc.

In my debugging, I have narrowed down that the error happens inside of the staticServer.serve(..) call itself, not in this code shown.

And the res.setHeader(..) call that I make before serve(..) seems to cause the error, though I don’t understand why. If I comment that line of code out, the error stops.

But my understanding is that me calling setHeader(..) only queues up a header to be sent. It’s not supposed to flush headers or anything, only prepare a header for later sending. I don’t have any other calls in that code path to res.writeHead(..) or anything, so I can’t figure out how the error is getting triggered.

I am aware that I could set this response header in the new nodeStatic.Server(..) constructor call. But I don’t want to do it there, because I actually need to be able to set specific headers on a per-request basis under certain conditions, and that approach sets headers for all static-file responses.

Can you help me figure out why, in only this one specific Slackbot request case, my call to setHeader(..) is triggering logic in node-static that causes this error? I’m really perplexed.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:12

github_iconTop GitHub Comments

1reaction
getifycommented, May 22, 2018

BTW, another reason I can’t just only set headers in the headers config of the constructor: certain headers have timestamps in them, and those would be calculated at the time the node server starts up, and never be re-calculated. But they actually should be relative to (recalculated at) each request. Otherwise, the longer the server stays alive without a restart, the more inaccurate that header’s timestamp would be. 😦

My only viable option here is to be able to call setHeader(..) upon each request. That’s why I need this problem fixed.

0reactions
1ns3cur3commented, May 24, 2018

So far, HEAD shouldn’t send headers which GET wouldn’t; which I guess you aren’t.

Other than that, yes, you can call writeHead as many times as you want, if you don’t call setHeaders().

Read more comments on GitHub >

github_iconTop Results From Across the Web

Error: Can't set headers after they are sent to the client
usually happens when you send several responses for one request. Make sure the following functions are called only once per request: res.json(); res.send();...
Read more >
Cannot set headers after they are sent to the client in JS
The "Cannot set headers after they are sent to the client" error occurs when the server in an express.js application sends more than...
Read more >
Understanding Node Error [ERR_HTTP_HEADERS_SENT]
This post describes why the Node Error [ERR_HTTP_HEADERS_SENT] cannot set headers after they are sent.
Read more >
Bonus Lecture - "Error: Can't set headers after they are sent."
Enroll now: https://pirple.thinkific.com/courses/the-nodejs-master-class.
Read more >
cannot set headers after they are sent to the client nextjs
This error message: Error: Can't set headers after they are sent. usually happens when you send several responses for one request. Make sure...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found