0

The goal of this exercise is to create an HTTP server that serves the same text file for each request that it receives. Here is my code. It doesn't work.

   var http = require ('http');
    var fs = require ('fs');
    var port = process.argv[2];
    var file = process.argv[3];
    var bl = require ('bl');

var server = http.createServer(function (request, response) {
    var stream = fs.createReadStream(file);
    var streamPipe = stream.pipe(response);
    response.write(streamPipe);
    });

server.listen(port);

I checked the correct answer, and that is to place the following code at the first line of the function, and remove my response.write() method:

response.writeHead(200, { 'content-type': 'text/plain' }); 

instead of my code, which I thought would write the data piped from the request stream to the response stream (line 10):

response.write(streamPipe)

I don't understand. Shouldn't response.writeHead go after the stream is established using the .createReadStream method, and not before?

Aren't I sending already existing data with response.write()? I want this to return a string and not an object, but the parameter has to be a string first, otherwise it doesn't work. The toString() method returns [object Object].

Can someone please explain the parameters of the writeHead method, and why it goes before everything else?

I realize this is a loaded question. I'm new to node, really excited to learn, but I just find it so difficult to understand. I have pretty basic JavaScript experience, and some Java, so I appreciate any and all help for an aspiring node.js developer.

Streamer
  • 173
  • 1
  • 1
  • 11

1 Answers1

1

Each HTTP response has three things: status, headers and content (which can be empty).

Status simply tells a status of response, e.g. 200 OK, 404 Not Found, 500 Internal Server Error, etc.

Headers is a sequence of key: value pairs which contain various meta data about the response like Content-Type: text/plain or Content-Length: 123456. Some of them are mandatory like Content-Length (actually there is a case when it is not, i.e. chunked encoding) and other are not.

And finally content is just a sequence of bytes.

And moreover that's exactly the order of those things in HTTP response stream. First there's status, then headers and at the end the content.

So you will always call response.writeHead method as first because this method sends both status and headers to the client. It accepts a pair (status_code, headers_object) as arguments where status_code is just a number and headers_object is an object {key1: value1, key2: value2} that will be converted to headers sequence.

Finally response.write method sends a chunk of the content to the client. It accepts a string as an argument.

Read more about response methods here: https://nodejs.org/api/http.html#http_response_write_chunk_encoding_callback

Note that you don't use response.write method explicitely in your example because stream.pipe(response) does that under the hood for you. Read this:

https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options

freakish
  • 54,167
  • 9
  • 132
  • 169
  • Very helpful. I checked out the documentation. Follow up q - can you explain in layman's terms what exactly happens with stream.pipe(response)? It sends the data from the source to the response, right? Including the response.writeHead() method fixed my problem and sent the string of content, but that happens before this "pipe" is even established. It's super confusing to me. – Streamer Mar 20 '16 at 01:03
  • @Azurasky You can treat `response` as a stream. So first thing you send to this stream is status and headers (i.e. you call `.writeHead()`). But the stream is still open. So now you call `stream.pipe(response)` which sends everything from a readable stream `stream` to a writable stream `response`. That way you fill the content of the response. That's why `.writeHead` has to happen before `.pipe`. Note that (by default) `.pipe` automatically closes `response` stream afterwards. I hope it is clear now. Feel free to ask more questions though. :) – freakish Mar 20 '16 at 14:45