We will cover the HTTP server module. Technically, you could write your HTTP server using the net
module, but you do not have to.
Some of these functions are very similar to the net
module functions. This should make sense as HTTP, at its core, is a network server.
All of these functions and objects are also used with the HTTPS module. The only difference is that for the options of createServer
and https.request
, you can pass certificates.
All of the following examples assume that the module has been loaded:
var http = require('http');
http.createServer([requestListener])
Much like net.createServer
, this is required to serve anything. The requestListener
parameter is attached to the request event.
Here is a simple example that just logs to the console any time a request is made:
var server = http.createServer(function (req, res) { console.log('Someone made a request!'); res.end(); }); server.listen(8080);
This is the server object that is returned from http.createServer
. This is the object that will respond to all requests.
We will start with the functions and look at each event separately as the events are important to handling requests.
This tells the server to listen on the supplied port, path, or file descriptor:
server.listen(port, [host], [callback]) server.listen(path, [callback]) server.listen(fd, [callback])
Although this function has three different ways to execute, you will most likely only use the network listener. In fact, the other two listeners are difficult, if not impossible, to even execute on Windows. Let's cover the last two quickly.
The path listener will use a local socket server, and the file descriptor will need a handle. If this sounds foreign, it means you will use the other method.
The network listener requires that the port be used. The host will default to localhost if nothing is passed in. In all the functions, a callback will be attached to the listening event.
Here is an example of listening on a network port with all the parameters defined:
var server = http.createServer(); server.listen(8080, 'localhost', function(){ console.log('The server is listening'); });
server.close([callback])
The http.Server
parameter is an EventEmitter
object. The events are also where the majority of work will be done.
This event fires when a request comes in:
server.on('request', function (req, res) { });
If you only listen to one event, this is the event to listen for. It has the request
and the server's response. The req
attribute will be http.IncomingMessage
, and the res
attribute will be http.ServerResponse
. We will look at both of these objects in this section. In addition to this, req
implements a readable stream interface, and res
implements a writable stream interface.
Here is an example of listening for a request:
server.on('request', function (req, res) { res.end(); console.log('A request was received'); });
This event fires when the client sends an HTTP upgrade:
server.on('upgrade', function (req, socket, buffer) { });
This is the request object when listening for the request event or from http.clientRequest
. This is a readable stream.
This is the URL that was requested:
message.url
This will be a string of the URL, including any query parameters. You can parse the string yourself or use Node's query string module and use the parse
function.
Here is a simple example that will serve any files in the current directory. Remember that this is only an example and does no error checking:
server.on('request', function (req, res) { var file = fs.createReadStream('.' + req.url); file.pipe(res); });
This is the data event from the readable stream interface.
If you have an incoming message, most likely, you would want to know what is in the message. As it is a readable stream, we will need to listen for the data event to get all the data out. When the data is exhausted, the end event will fire.
Here is an example that creates listeners for the data and end event:
var data = ''; response.on('data', function (chunk) { console.log(chunk); data += chunk; }); response.on('end', function () { console.log(data); });
This is the response that the HTTP server creates for the event request. Each request needs a response, and this is it. This implements a writable interface.
This will write the HTTP response header:
response.WriteHead(statusCode, [headers])
This writes the header for the response. This needs to be called before response.write
. If it is not, then the server will send it for you with the headers you have set.
statusCode
is the HTTP status code of the response. A header
is an object with the name of the header as a property and the value as the value.
Here is an example that writes the header:
server.on('request', function (req, res) { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(); });
This sets the status code of the response:
response.statusCode
This writes a specific header:
response.setHeader(name, value)
In the same way that
statusCode
must be called instead of writeHead
, setHeader
must be called instead of writeHead
. This can be called multiple times to set multiple headers.
Here is an example of using statusCode
and setHeader
together:
server.on('request', function (req, res) { res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); res.setHeader('Custom-Header', 'Custom-Value'); res.end(); });
This is the function that writes the response body:
response.write(chunk, [encoding])
The response.write
parameter is a writable stream, so this interface can be used. A chunk can be a buffer or string. The encoding is optional as it will default to UTF8. Here is an example that writes a simple HTML page as the response:
server.on('request', function (req, res) { res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); res.write('<html><body><h1>Hello!</h1></body></html>'); res.end(); });
response.end([data], [encoding])
The response
parameter is a writable stream, so we must end the stream when we are done writing. Data is any optional data that needs to be written, and encoding will default to UTF8. All of the examples for response have used res.end
. If you do not end the response, the browser will wait for a response from the server.
This makes a request using HTTP:
http.request(options, [callback])
Node.js allows you to consume HTTP as well as serve it. The options object has many properties that can be set. Here is a list of them:
host
hostname
port
localAddress
socketPath
method
path
headers
auth
agent
Every option is not required for each request. Most of the time, only hostname
, port
, path
, and method
are needed to make a request. The options parameter can also be a URL as a string.
The callback will be attached to the response event. The request object is a writable stream so that data can be sent to the server. Here is an example that makes a request to Packt Publishing:
var request = http.request({ host: 'www.packtpub.com', port: 80, path: '/', method: 'GET' }, function (res) { console.log(res); }); request.end();
This is the convenience method for a GET
request:
http.get(options, [callback])
This works in a manner similar to http.request
, except it automatically sends an empty request and calls the end function. If you are only making a GET
request, this can save some boilerplate code.
Here is an example that requests Packt Publishing:
http.get('http://www.packtpub.com', function (res) { console.log(res); });
This is the object that is returned from http.request
.
request.end([data], [encoding])
This is the response event. It lets you know that the remote server has responded:
request.on('response', function(response){})
This event fires when the remote server responds. The response object in the callback will be http.incomingMessage
.
If no response handler is added, the server response will be discarded. If there is a response handler, then Node.js will start to buffer the response to memory. If you do not read it back out, you can cause the server to crash.
Here is an example listener that reads the data from the response:
var request = http.request({host: 'www.google.com', path: '/', port: 80, method: 'GET'}); request.on('response', function (response) { var data = ''; response.on('data', function (chunk) { console.log(chunk); data += chunk; }); response.on('end', function () { console.log(data); }); });
18.117.76.204