FreeCodeCamp and Learning Node: HTTP File Server

Last time we learned how to return a time in response to a request.  Now we’re going to learn to return a file in response to a request.  We’re coming towards the end of the Node tutorials and so things are getting more interesting and complex.  This exercise was an interesting one; we’ll be serving files as part of the challenges for FreeCodeCamp in the future…

For now though, let’s look at  the Directions and Hints:

 ## HTTP FILE SERVER (Exercise 11 of 13)
  Write an HTTP server that serves the same text file for each request it receives.
  Your server should listen on the port provided by the first argument to your program.
  You will be provided with the location of the file to serve as the second command-line argument. You must use the fs.createReadStream() method to stream the file contents to the response.
 ─────────────────────────────────────────────────────────────────────────────
 ## HINTS
  Because we need to create an HTTP server for this exercise rather than a generic TCP server, we should use the http module from Node core. Like the net module, http also has a method named http.createServer() but this one creates a server that can talk HTTP.
  http.createServer() takes a callback that is called once for each connection received by your server. The callback function has the signature:
     function callback (request, response) { /* … */ }
  Where the two arguments are objects representing the HTTP request and the corresponding response for this request. request is used to fetch properties, such as the header and query-string from the request while response is for sending data to the client, both headers and body.
  Both request and response are also Node streams! Which means that you can use the streaming abstractions to send and receive data if they suit your use-case.
  http.createServer() also returns an instance of your server. You must call server.listen(portNumber) to start listening on a particular port.
  A typical Node HTTP server looks like this:
     var http = require(‘http’)
     var server = http.createServer(function (req, res) {
       // request handling logic…
     })
     server.listen(8000)
  Documentation on the http module can be found by pointing your browser here:
  file:///home/ubuntu/.nvm/versions/node/v4.4.3/lib/node_modules/learnyounode/node_apidoc/http.html

  The fs core module also has some streaming APIs for files. You will need to use the fs.createReadStream() method to create a stream representing the file you are given as a command-line argument. The method returns a stream object which you can use src.pipe(dst) to pipe the data from the src stream to the dst stream. In this way you can connect a filesystem stream with an HTTP response stream.

I admit that at first the directions and hints were a little cryptic, but this exercise turned out to be much easier than I thought.

First, scanning through the material above, we’re going to need http and fs, so we write the require statements for those.  Then, we note that it states that the port and the file path will be provided as command line arguments in our old friend process.argv.  So, as in the past many exercises, we assign those to variables.  That wraps up assignments, and also the easy part.

Next, they give us the skeleton of the server:

</div>
<div> var server = http.createServer(function (req, res) {</div>
<div>       // request handling logic...</div>
<div>     })</div>
<div>     server.listen(8000)</div>
<div>

8000 will of course be replaced by our port, and so our program now looks like this so far:

</div>
<div>var http = require('http');</div>
<div>var fs = require('fs');</div>
<div>var port = process.argv[2];</div>
<div>var filePath = process.argv[3];</div>
<div></div>
<div>var server = http.createServer(function (req, res) {</div>
<div>       // request handling logic...</div>
<div>})</div>
<div>server.listen(port);</div>
<div>

Now we need to write the “request handling logic” they have in there.  We know, from the directions and hints, that we need fs.createReadStream(), and that we’ll also need a src.pipe(dst).  The info on createReadStream is here:

https://nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_createreadstream_path_options

So, what goes in the parentheses (the parameters) is the file path, which we have a variable for called filePath.  That’s the SOURCE, so we’ll assign it to a variable called src, thus:

</div>
<div>var src = fs.createReadStream(filePath);</div>
<div>

Now, finally, we have src.pipe(dst).  src is the SOURCE (see what I did there?) and dst is the stream we are sending it to.  Here’s where it gets a little tricky.  What are we sending it to?  Well, in the hints we are told, “Both request and response are also Node streams!”  Ahhh, so we want to use the response stream!  So:

</div>
<div>src.pipe(res);</div>
<div>

And…..we pass!  Here’s the final program:

</div>
<div>var http = require('http');</div>
<div>var fs = require('fs');</div>
<div>var port = process.argv[2];</div>
<div>var filePath = process.argv[3];</div>
<div></div>
<div>var server = http.createServer(function (req, res) {</div>
<div>       // request handling logic...</div>
<div>       var src = fs.createReadStream(filePath);</div>
<div>       src.pipe(res);</div>
<div></div>
<div></div>
<div>});</div>
<div>server.listen(port);</div>
<div>

See you next time!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s