The HTTP server object is the foundation of all Node.js web applications. The object itself is very close to the HTTP protocol, and its use requires knowledge of that protocol. In most cases, you'll be able to use an application framework such as Express that hides the HTTP protocol details, allowing the programmer to focus on business logic.
We already saw a simple HTTP server application in Chapter 2, Setting up Node.js, which is as follows:
var http = require('http'); http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello, World! '); }).listen(8124, '127.0.0.1'); console.log('Server running at http://127.0.0.1:8124');
The http.createServer
function creates an http.Server
object. Because it is an EventEmitter
, this can be written in another way to make that fact explicit:
var http = require('http'); var server = http.createServer(); server.on('request', (req, res) => { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello, World! '); }); server.listen(8124, '127.0.0.1'); console.log('Server running at http://127.0.0.1:8124');
The request
event takes a function, which receives request
and response
objects. The request
object has data from the web browser, while the response
object is used to gather the data to be sent in the response. The listen
function causes the server to start listening and arranging to dispatch an event for every request arriving from a web browser.
Now, let's look at something more interesting with different actions based on the URL.
Create a new file named server.js
containing the following code:
var http = require('http'); var util = require('util'); var url = require('url'); var os = require('os'); var server = http.createServer(); server.on('request', (req, res) => { var requrl = url.parse(req.url, true); if (requrl.pathname === '/') { res.writeHead(200, {'Content-Type': 'text/html'}); res.end( `<html><head><title>Hello, world!</title></head> <body><h1>Hello, world!</h1> <p><a href='/osinfo'>OS Info</a></p> </body></html>`); } else if (requrl.pathname === "/osinfo") { res.writeHead(200, {'Content-Type': 'text/html'}); res.end( `<html><head><title>Operating System Info</title></head> <body><h1>Operating System Info</h1> <table> <tr><th>TMP Dir</th><td>${os.tmpDir()}</td></tr> <tr><th>Host Name</th><td>${os.hostname()}</td></tr> <tr><th>OS Type</th><td>${os.type()} ${os.platform()} ${os.arch()} ${os.release()}</td></tr> <tr><th>Uptime</th><td>${os.uptime()} ${util.inspect(os.loadavg())}</td></tr> <tr><th>Memory</th><td>total: ${os.totalmem()} free: ${os.freemem()}</td></tr> <tr><th>CPU's</th><td><pre>${util.inspect(os.cpus())}</pre></td></tr> <tr><th>Network</th><td><pre>${util.inspect(os.networkInterfaces())}</pre></td></tr> </table> </body></html>`); } else { res.writeHead(404, {'Content-Type': 'text/plain'}); res.end("bad URL "+ req.url); } }); server.listen(8124); console.log('listening to http://localhost:8124');
To run it, type the following command:
$ node server.js listening to http://localhost:8124
This application is meant to be similar to PHP's sysinfo
function. Node's os
module is consulted to give information about the server. This example can easily be extended to gather other pieces of data about the server:
A central part of any web application is the method of routing requests to request handlers. The request
object has several pieces of data attached to it, two of which are useful for routing requests, the request.url
and request.method
fields.
In server.js
, we consult the request.url
data to determine which page to show, after parsing (using url.parse
) to ease the digestion process. In this case, this lets us do a simple comparison of the pathname
to determine what to do.
Some web applications care about the HTTP verb (GET
, DELETE
, POST
, and so on) used and must consult the request.method
field of the request
object. For example, POST
is frequently used for FORM
submissions.
The pathname
portion of the request URL is used to dispatch the handler code. While this routing method, based on simple string comparison, will work for a small application, it'll quickly become unwieldy. Larger applications will use pattern matching to use part of the request URL to select the request handler function and other parts to extract request data out of the URL. We'll see this in action while looking at Express later in the Getting started with Express section.
If the request URL is not recognized, the server sends back an error page using a 404
result code. The result code informs the browser about the status of the request, where a 200
code means everything is fine, and a 404
code means the requested page doesn't exist. There are, of course, many other HTTP response codes, each with their own meaning.