60

I have written a small API which uses the Node js "restify" framework. This API receives a request (actually anything after "/") and then send that request to another server. Get the response back from server and passes the response back to original source of request. For this API I am using both restify server and client.

Below is that API code for better understanding.

var apiServer = require('apiServer');
apiServer.start();

var restify = require('restify');
var assert = require('assert');

function onRequest(request, response, next)
{
    var client = restify.createStringClient({ 
        url: 'http://example.com'
    });

    client.get('/' + request.params[0], function(err, req, res, data) {
        assert.ifError(err);

        response.setHeader('Content-Type', 'text/html');
        response.writeHead(res.statusCode);
        response.write(data);
        response.end();
    });
    next();
}

function start()
{
    var server = restify.createServer();
    server.get(/^\/(.*)/, onRequest);
    server.listen(8888);

    console.log("Server has started.");
}

exports.start = start;

Now I need to know the difference between response.write and response.send of Node.js. Because with response.write I can set header and write in it but it is not possible to do anything with headers when I use response.send. When I use response.send with setHeader() or writeHeader() I get this error:

http.js:691
    throw new Error('Can\'t set headers after they are sent.');
          ^
    Error: Can't set headers after they are sent.

There is also another thing. With response.send() I get the complete HTML output on the screen like:

<!DOCTYPE html>\n<html>\n\t<head></head></html> ..... "bla bla bla"

But with response.write I do not get the html on screen but only the text "bla bla bla".

It would be great if someone can explain me the differences.

Jawa
  • 2,336
  • 6
  • 34
  • 39
user3275959
  • 611
  • 1
  • 5
  • 4

4 Answers4

68

response.send(msg) is equal to response.write(msg);response.end();

Which means, send can only be called once, write can be called many times, but you must call end yourself.

Flying Fisher
  • 1,932
  • 2
  • 13
  • 13
  • 1
    But what about the types of out that I received with those two functions? Like I said, res.write does not print the entire html on screen or browser but res.send does. – user3275959 Feb 13 '14 at 09:37
  • 1
    You want to display html code in browser? If so, just add head content-type, like `response.writeHead('content-type','text/plain')` – Flying Fisher Feb 14 '14 at 04:32
  • 8
    Basically, `response.send(msg)` is the same as `response.end(msg)`. You just have to type an extra s. – theonlygusti Feb 02 '15 at 19:17
  • @theonlygusti This is not entirely true. Consider `response.write("Hello");response.end(" World")` vs `response.write("Hello");response.send(" World")`. The later would give me an error saying "Error: Can't set headers after they are sent." Not sure what is going on. – Kun Jun 29 '17 at 02:58
  • 2
    @Kun Look at the structure of an HTTP request -- by the time you've started sending the body of the request ("Hello") you _have_ to have sent the headers already. `send` attempts to guess and set headers based on the type of the object you pass it, so it fails if the headers are already locked. – Nic May 30 '18 at 22:17
  • @NicHartley Ah, I see – Kun Jun 12 '18 at 17:55
37

I can't find response.send() in the docs, but I assume .send() will fill in and send the response so can only be called once, whereas .write() will just write the response, but you have to send it using response.end()

This means you can edit the headers using .write() because the response has not been sent yet.

EDIT :

response.send() is part of the restify Response API wrapper

Jim Jeffries
  • 9,841
  • 15
  • 62
  • 103
  • But what about the types of out that I received with those two functions? Like I said, res.write does not print the entire html on screen or browser but res.send does. – user3275959 Feb 13 '14 at 09:38
  • @user3275959 and also could you explain the differences in output a bit more? – Jim Jeffries Feb 13 '14 at 09:52
  • res.send() is a deprecated method. see http://stackoverflow.com/questions/30550049/node-express-errror-express-deprecated-res-sendstatus-use-res-sendstatusst – Oliv Feb 22 '17 at 10:40
31

res.send() is part of Express.js instead of pure Node.js.

Just an side observation. My app sometimes send back a very large Json object ( HighChart object that contains over 100k points). With res.send() sometimes it hangs and choke up the server, whereas res.write() and res.end() handle it just fine.

I also noticed a memory spike when res.send() is invoked.

Gäng Tian
  • 1,588
  • 2
  • 18
  • 26
  • 2
    This is key! res.send is only in Express note Node. It also performs a bunch of magic like setting content-length and content-type. If you want to have absolute control, you need res.write and res.end. In fact the express compress module at this point only runs with res.write & res.end. – CMCDragonkai Apr 26 '15 at 06:09
  • 1
    Woops disregard the whole not working in Express: https://github.com/expressjs/compression/issues/39 – CMCDragonkai Apr 26 '15 at 06:21
  • 1
    working opposite at my end, res.send(json) is helping me to return a large json very fine whereas res.write(json) with res.end() doesn't do the job – Adil May 24 '17 at 06:27
3

I was trying to send huge text data(295mb) over http using res.send(data) and res.write(data). I noticed that res.send(data) is slower than res.write(data). I observed following things.

res.send(data): it can be called only once and it sends data in chunk of some buffer size to client and then again comes back and sends another chunk of buffer size so there is a lot of back and forth http communication.

res.write(data): It can be called multiple times followed by res.end() and It creates buffer size based on whole data and sends over http so it would be faster in case of huge amount of data.

Shashi3456643
  • 2,021
  • 17
  • 21