I am creating simple application to send a simple message hello when the user requests get request of home page.
app.get("/",(req,res)=>{
setInterval(function(){
res.status(200);
res.send("hello");
},5000)
})
The Idea is to send response after 5 seconds.
The compiler is throwing error after sending response .
The error is as follows
node:_http_outgoing:663
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:400:5)
at ServerResponse.setHeader (node:_http_outgoing:663:11)
at ServerResponse.header (C:\Users\prudh\OneDrive\Documents\projects\whatsapp\node_modules\express\lib\response.js:794:10)
at ServerResponse.send (C:\Users\prudh\OneDrive\Documents\projects\whatsapp\node_modules\express\lib\response.js:174:12)
at Timeout._onTimeout (C:\Users\prudh\OneDrive\Documents\projects\whatsapp\index.js:40:13)
at listOnTimeout (node:internal/timers:564:17)
at process.processTimers (node:internal/timers:507:7) {
code: 'ERR_HTTP_HEADERS_SENT'
}
Why am I facing this error message.
This is the basic code block so I have not tried anything.
setInterval runs function repeatedly, so you see this error when it tries to run function second time, because response is already sent to client. Use setTimeout instead to delay function:
app.get("/",(req,res) =>
setTimeout(() => res.status(200).send("hello"), 5000)
)
Related
I have an http server listening on port 9090 - piping the request to stdout like so:
let server = http.createServer((req, res) => {req.pipe(process.stdout)})
server.listen(9090)
When I send it something with curl like so:
curl -XGET -T - 'http://localhost:9090' < /tmp/text-input
it works, and I see the output on the server's terminal
but when I try the following in node:
const http = require('http')
const nurl = new URL("http://localhost:9090")
let request = http.request(nurl)
request.on('response', (res) => {
process.stdin.pipe(request)
})
request.end() // If I emit this, nothing happens. If I keep this, I get the below error
and try to run it like so: node request.js < /tmp/text-input, I'm getting the following error:
node:events:368
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at new NodeError (node:internal/errors:371:5)
at write_ (node:_http_outgoing:748:11)
at ClientRequest.write (node:_http_outgoing:707:15)
at ClientRequest.<anonymous> (/home/tomk/workspace/js-playground/http.js:17:7)
at ClientRequest.emit (node:events:390:28)
at HTTPParser.parserOnIncomingClient (node:_http_client:623:27)
at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
at Socket.socketOnData (node:_http_client:487:22)
at Socket.emit (node:events:390:28)
at addChunk (node:internal/streams/readable:324:12)
Emitted 'error' event on ClientRequest instance at:
at emitErrorNt (node:_http_outgoing:726:9)
at processTicksAndRejections (node:internal/process/task_queues:84:21) {
code: 'ERR_STREAM_WRITE_AFTER_END'
}
I want to pipe my stdin to an http server the same way I can with curl -T -. What is wrong with my request code?
Short answer
To send chunked encoding messages in node, use the POST method:
let request = http.request(url, { method: 'POST' })
process.stdin.pipe(request)
Edit: A more straigt forward approach
Or, to send any request method with chunked encoding:
let request = http.request(url)
request.setHeader("transfer-encoding", "chunked")
request.flushHeaders()
process.stdin.pipe(request)
Slightly longer (yet partial) answer
I opened a listening netcat (listen on plain tcp) like so nc -l 9090 to view how the request from curl differs from my code and found a few key differences in the headers.
In curl, the header Transfer-Encoding: chunked appeared, but was missing from the request my code sent out. Also, my code had a header Connection: closed
I logged the request object and found that useChunkedEncodingByDefault is set to false, which was confusing given the quote from the nodejs http docs:
Sending a 'Content-Length' header will disable the default chunked encoding.
Implying that it should be the default.
But then I found this in the source of node
if (method === 'GET' ||
method === 'HEAD' ||
method === 'DELETE' ||
method === 'OPTIONS' ||
method === 'TRACE' ||
method === 'CONNECT') {
this.useChunkedEncodingByDefault = false;
} else {
this.useChunkedEncodingByDefault = true;
}
Edit
To send chunked encoding anyway, I (eventually) found that I need to explicitly add the Transfer-Encoding: Chunked header explicitly:
request.setHeader("transfer-encoding", "chunked")
# and then
request.flushHeaders()
So, in conclusion, node doesn't allow sending send by default GET requests with chunked encoding, but curl does. Odd, and unfortunately not documented (as far as I could find), but the important thing I got it working
C:\Users\KUMAR\Desktop\DigitelMall\node_modules\mysql\lib\protocol\Parser.js:437
throw err; // Rethrow non-MySQL errors
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (C:\Users\KUMAR\Desktop\DigitelMall\node_modules\express\lib\response.js:718:10)
at ServerResponse.send (C:\Users\KUMAR\Desktop\DigitelMall\node_modules\express\lib\response.js:163:12)
at ServerResponse.json (C:\Users\KUMAR\Desktop\DigitelMall\node_modules\express\lib\response.js:249:15)
at updateEntity (C:\Users\KUMAR\Desktop\DigitelMall\controllers\MainMenu.js:81:40)
at Query.pool.query (C:\Users\KUMAR\Desktop\DigitelMall\models\CommonModel.js:110:20)
at Query. (C:\Users\KUMAR\Desktop\DigitelMall\node_modules\mysql\lib\Connection.js:526:10)
at Query._callback (C:\Users\KUMAR\Desktop\DigitelMall\node_modules\mysql\lib\Connection.js:488:16)
at Query.Sequence.end (C:\Users\KUMAR\Desktop\DigitelMall\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
You are trying to send the response to a request that you had already responded to.
The response could have been sent by the framework you are using if it implements a default error handler.
I get a "can't set headers after they're sent" error, which I understand may be due to sending a response from my server more than once, however it doesn't seem to be the case with my code, at least on the surface. I make a query to dbpedia in order to obtain some resources, which I then send back to my client. Here's the code:
app.get("/",function(req,res,next){
if (req.query.titolo){
var response ;
let [ artist, title ] = getArtistTitle(req.query.titolo);
title = title.replace(" ","_");//for dbpedia resource names
const prefixes = {
dbo: "http://dbpedia.org/ontology/",
db: "http://dbpedia.org/resource/"
}
DbPediaClient.setOptions('application/sparql-results+json',prefixes);
DbPediaClient.query("SELECT ?abstract WHERE { db:"+title+
" dbo:abstract ?abstract. FILTER langMatches(lang(?abstract),'en') }")
.then((data)=>{
response = data["results"]["bindings"][0]["abstract"]["value"] ;
return res.json({abstract: response}) ;
})
.catch((error)=>{
console.log(error);
});
}
});
I use virtuoso-sparql-client to make a query to http://dbpedia.org/sparql (DbPediaClient is initialized outside of this function). I've already tried using res.send instead of res.json, and it still gives the same error. Which by the way it's the following:
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at ServerResponse.header (/home/lorenzo/Scrivania/ProgettoTechweb/AlphaTube/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/home/lorenzo/Scrivania/ProgettoTechweb/AlphaTube/node_modules/express/lib/response.js:170:12)
at DbPediaClient.query.then (/home/lorenzo/Scrivania/ProgettoTechweb/AlphaTube/server.js:43:15)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
If you need more info please ask.
Express is a framework that handles request/response cycles by iterating through routes that match the path specified in an HTTP request and letting your code send the response in each match or call next() if it didn't send one. The problem here is you have the following:
app.get("/",function(req,res,next){
res.sendFile(...);
next();
});
app.get("/",function(req,res,next){
if (req.query.titolo){
...
res.json(...);
}
});
This code means
Whenever I get an HTTP request to / then send some HTML, then if the request contains titolo in the query, send some JSON as well.
Express is telling you that you can't send anything else since you already sent the HTML.
One solution would be to move the API route above the HTML:
app.get("/",function(req,res,next){
if (req.query.titolo){
...
res.json(...);
} else {
next();
}
});
app.get("/",function(req,res){
res.sendFile(...);
});
which means
Whenever I get an HTTP request to /, if the request contains titolo in the query, send some JSON, otherwise send some HTML.
But my recommendation would be to move the API route to a different path that doesn't collide with the route for your static file, which is a lot more typical for HTTP servers.
http.js:732
throw new Error('Can\'t render headers after they are sent to the client.'
^
Error: Can't render headers after they are sent to the client.
at ServerResponse.OutgoingMessage._renderHeaders (http.js:732:11)
at ServerResponse.writeHead (http.js:1153:20)
at ProxyServer.<anonymous> (/home/ec2-user/.meteor/packages/meteor-tool/.1.1.4.1tjewoi++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/tools/run-proxy.js:96:21)
at ProxyServer.emit (/home/ec2-user/.meteor/packages/meteor-tool/.1.1.4.1tjewoi++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/lib/node_modules/http-proxy/node_modules/eventemitter3/index.js:100:27)
at ClientRequest.proxyError (/home/ec2-user/.meteor/packages/meteor-tool/.1.1.4.1tjewoi++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/lib/node_modules/http-proxy/lib/http-proxy/passes/web-incoming.js:140:16)
at ClientRequest.emit (events.js:117:20)
at Socket.socketOnData (http.js:1593:9)
at TCP.onread (net.js:528:27)
Meteor server throws this error or Production instance only. I'm running the same repository in Staging and it runs smoothly. Meteor throws this error even when nobody is interacting with the client (Crons run on server during regular intervals). I'm not able to figure out the reason. People have faced this problem for different issues, but I didn't find it familiar with my case.
I suspect this code is throwing this error. Not sure though
updateFunction = function(event) {
var res = Meteor.http.call("GET", "http_url"+ event);
var contents = EJSON.parse(res.content).tracks["0"];
if(!contents) return;
var events = [];
contents.map(function(ele){
if(ele.type == "snap") {
ele._id = ele.id;
delete ele.id;
events.push(ele);
}
});
CollectionName.upsert(event,{"$set":{"data": events}});
}
I wonder why such simple http request is not working...
http = require("http")
url = "http://nodejs.org/"
console.log "Try a request to #{url}..."
reqHttp = http.request url, (response) ->
console.log "Request to #{url}"
response.on 'data', (chunk) -> console.log "chunk: ", chunk
reqHttp.on 'error', (error) -> console.log "reqHttp error", error
After a minute or so it returns:
reqHttp error { [Error: socket hang up] code: 'ECONNRESET' }
To make sure it is not a problem on my environment, I tried the request module and worked just fine:
request = require("request")
url = "http://nodejs.org/"
request url, (error, response, body) ->
console.log body if not error and response.statusCode is 200
It seems I'm not the only one.
So, I have a workaround for my problem (using request module), but I'd like to know why I can't use the buind-in http request. Is it buggy or unreliable? (Node.js version 0.8.21)
OK, this is really simple. You are constructing an http request but did not finish sending it. From the link you gave itself:
req.write('data\n'); //Write some data into request
req.write('data\n');
req.end(); //Finish sending request let request go. Please do this
Since you never used req.end(), it hung up since it never got completed. Node reset the inactive request
reqHttp error { [Error: socket hang up] code: 'ECONNRESET' }