Advanced Servers
Static File Server
One popular use case is to serve files directly from a directory on our machine.
For this, we will setup a configuration module at config.js that contains:
'use strict'
module.exports = {
staticPath: __dirname // process.cwd()
}Which our application will include via require('./config') (extensions are optional).
Read File
The most basic way of accomplishing this, is to use fs.readFile
'use strict'
// Requires
const httpUtil = require('http')
const fsUtil = require('fs')
const pathUtil = require('path')
const urlUtil = require('url')
const config = require('./config')
// Server
httpUtil.createServer(function (req, res) {
const file = urlUtil.parse(req.url).pathname
const path = pathUtil.join(config.staticPath, file)
fsUtil.exists(path, function (exists) {
if (!exists) {
res.statusCode = 404
return res.end('404 File Not Found')
}
fsUtil.readFile(path, function (error, data) {
if (error) {
console.log('Warning:', error.stack)
res.statusCode = 500
return res.end('500 Internal Server Error')
}
return res.end(data)
})
})
}).listen(8080)Test it: curl http://localhost:8080/server-static.js
However, readFile will read the entire file, then send the entire file. Take a moment to imagine how this not optimum.
Streams
The next most basic way, is to use a Readable Stream via fs.createReadStream.
Test it: curl http://localhost:8080/server-static.js
Directories
Getting more advanced here. What about outputting the contents of directories too? For this, we can use fs.readdir
Test it: curl http://localhost:8080
Applying Abstractions
Considering the static file server example is incredibly common. Lets think of ways we can abstract out the serving of static files so we can re-use that functionality easily.
Desiring a solution like:
One could come up with the following:
Note the introduction of a next callback. This allows us to chain additional or custom functionality.
Introduction to Middlewares
In our previous example of writing the serveStatic what we effectively did was create a middleware, albiet a basic middleware but a middleware nonetheless. Naturally, there are already plenty of other middlewares published as modules by other people. This is helped by the middleware framework Connect originally by TJ Holowaychuk.
Before we can install anything, we need to first initialise our directory as a node.js project:
That will create a package.json file that will keep track of the dependencies we install.
We can install connect like so:
Using connect, our static file server example would become:
Much simpler. Notice how the middlewares are like a waterfall, it hits the first, then if the first doesn't know what to do, the logic will flow through to the next middleware (accomplished by the previous middleware calling the next callback inside it).
Connect has plenty of other middlewares available for it. Official middlewares for connect are listed on its website with 3rd party middleware listed on GitHub.
There is even existing middlewares for what we've just accomplished. We can install them like so:
And consume them like so:
Introduction to Web Frameworks
There are a few web frameworks for node. The most used is Express originally by TJ Holowaychuk.
Perhaps by now you would have noticed the amount of individuals mentioned who have created awesome things, this is very much the case, anyone can have an impact.
Express can be thought of as a layer that sits ontop of connect and node's http module. It provides its own middleware and uses its own request and response objects that inherit from those of node's http module. The benefit over just using connect are:
Addition of routing
Common functionality provided through a friendly syntax
We can install express like so:
The following is what a simple hello world server would look like with express:
It is important to note that the line
var server = app.listen(8080);is the same as doingvar server = require('http').createServer(app).listen(8080);. You will need to remember this when interfacing with other modules - some modules like to interface with the express instanceappwhile others like to interface with the node http server instanceserverinstead.
And this is what our static file server will look like with express:
Notice the nicer syntax for setting the status code of the response. Before it was res.statusCode = 404; now it is the first argument of res.send. This is what we meant by express providing a nicer syntax.
Last updated
Was this helpful?