19

Code explanation: I am returning specific HTML file when user visit specific url:

const http = require('http');
const fs = require('fs');

fs.readFile('./funkcionalnosti-streznika.html', function(err1, html1) {
    fs.readFile('./posebnosti.html', function(err2, html2) {
        if (err1 || err2) {
            throw new Error();
        }

        http.createServer(function(req, res) {
            if (req.url == '/funkcionalnosti-streznika') {
                res.write(html1);
                res.end();
            }
            if (req.url == '/posebnosti') {
                res.write(html2)
                res.end();
            } else {
                res.write('random');
                res.end();
            }
        }).listen(8080)
    })
});

on terminal I've got this error when I visit localhost:8080/funkcionalnosti-streznika:

events.js:288
      throw er; // Unhandled 'error' event
      ^

Error [ERR_STREAM_WRITE_AFTER_END]: write after end
    at write_ (_http_outgoing.js:637:17)
    at ServerResponse.write (_http_outgoing.js:629:15)
    at Server.<anonymous> (/*filelocation*/:19:21)
    at Server.emit (events.js:311:20)
    at parserOnIncoming (_http_server.js:784:12)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:119:17)
Emitted 'error' event on ServerResponse instance at:
    at writeAfterEndNT (_http_outgoing.js:692:7)
    at processTicksAndRejections (internal/process/task_queues.js:85:21) {
  code: 'ERR_STREAM_WRITE_AFTER_END'

I think there is I problem when I close the response too early. How should I change this to be async?.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
Tadej
  • 301
  • 1
  • 2
  • 5
  • Does this answer your question? ["write after end" error in a server made with nodejs](https://stackoverflow.com/questions/50140841/write-after-end-error-in-a-server-made-with-nodejs) – Mehdi Mar 16 '20 at 23:09

5 Answers5

35

You have already realized what the problem is. Let's take a look at this code:

    http.createServer(function(req, res) {
        if (req.url == '/funkcionalnosti-streznika') {
            res.write(html1);
            res.end();
        }
        if (req.url == '/posebnosti') {
            res.write(html2)
            res.end();
        } else {
            res.write('random');
            res.end();
        }
    }).listen(8080)

Let's suppose that req.url is '/funkcionalnosti-streznika'. What happens? It enters the first if, writes html1 and ends res. Then it is checked against '/posebnosti', but it's different, because the first if was true. This means that the else branch will be executed, so res.write('random'); is called, but res was already closed in the first if. Suggestion:

http.createServer(function(req, res) {
    if (req.url == '/funkcionalnosti-streznika') {
        res.write(html1);
        res.end();
    }
    else if (req.url == '/posebnosti') {
        res.write(html2)
        res.end();
    } else {
        res.write('random');
        res.end();
    }
}).listen(8080)
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
  • I was taking a look at the documentation and I still don't understand: does the res.end() method only signals that the message is complete or does it actually ends the request? is there any other way of using it in the above example as you would with a "return" at the end of a if condition to ignore the other cases? – Marcus Castanho May 25 '21 at 02:32
  • 2
    @MarcusCastanho kindly read https://nodejs.org/api/stream.html#stream_writable_end_chunk_encoding_callback basically you end writing into the writable. In the code above you could remove all the `res.end()` lines and put them after the if-else if-else blocks, since it is called in all cases. `return` assigns a value to a function and stops its execution. res.end signifies the end of the writing. You could do `return res.end();` if that helps. – Lajos Arpad May 25 '21 at 15:15
11

Just write return after every if, this will stop further execution of the code.

harshit bhalla
  • 111
  • 1
  • 3
4

Instead of multiple "if" condition use "if else" or just return every "if" condition.

// ...
if (req.url == '/funkcionalnosti-streznika') {
  res.write(html1);
} else if (req.url == '/posebnosti') {
  res.write(html2);
} else {
  res.write('random');
}
res.end();
// ...
David Mason
  • 2,917
  • 4
  • 30
  • 45
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 04 '22 at 03:49
0

You can check using inside your API using if (res.writableEnded) return; to see if your middleware have already wrote to the response stream (it used to be response.finished but got deprecated)

Korayem
  • 12,108
  • 5
  • 69
  • 56
0

/*if (req.url == '/funkcionalnosti-streznika') {
return res.end('case-1');
}
if (req.url == '/posebnosti') {
return res.end('case-2');
}
res.end('other case');
*/

It help me

Danisher
  • 1
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 04 '23 at 09:24