lib/server.js

1.
var http = require("http");
2.

			
3.
/**
4.
 * This is the server class. With you can easily create and manage a http server. This class is 
5.
 * also needed when working with the cerus-router. When there is a request the callback function is
6.
 * called. This callback has to be set if you want to receive incoming requets. It must be noted 
7.
 * that this name can be confusing and therefor a different module is on it's way. This means this 
8.
 * class will be deprecated somewhere in the near future.
9.
 * @example
10.
 * // in this example a server is created and started
11.
 * cerus.server().callback(function(req, res) {});
12.
 * // -> now all incoming request will call this function
13.
 * 
14.
 * cerus.server().start();
15.
 * // -> starts the server on port 80
16.
 * @class server
17.
 */
18.
class server {
19.
	constructor(cerus) {
20.
		this._server = http.createServer(function(req, res) {
21.
			if(typeof this._func === "function") {
22.
				this._func(req, res);
23.
			}
24.
		}.bind(this));
25.
		this._port = 80;
26.
		this._cerus = cerus;
27.
	}
28.

			
29.
	/**
30.
	 * This function sets the callback function for the server. This function will be called when 
31.
	 * there is a new request. The function will be called with to parameters: req and res. The 
32.
	 * req parameter contains the request (http.IncomingMessage) and the res parameter the response
33.
	 * (http.ServerResponse). For a custom and better req and res take a look at the cerus-router 
34.
	 * module. 
35.
	 * @example
36.
	 * cerus.server().callback(function(req, res) {});
37.
	 * // -> this will set the callback function
38.
	 * @summary Sets the callback that will be called for incoming requests.
39.
	 * @param {Function} func The callback function.
40.
	 * @function callback
41.
	 */
42.
	callback(func) {
43.
		if(typeof func !== "function") {
44.
			throw new TypeError("the argument func must be a function");
45.
		}
46.

			
47.
		this._func = func;
48.
	}
49.

			
50.
	/**
51.
	 * This function is used to start the server. You can also supply a port if you don't want to 
52.
	 * use the one that is currently set. The server cannot be started when it is already running.
53.
	 * This function will also return a promise. This promise will call the "started" event when 
54.
	 * the server has been started.
55.
	 * @example
56.
	 * cerus.server().start(); // or cerus.server().listen();
57.
	 * // -> starts the server on the default port 80
58.
	 * @summary Starts the server.
59.
	 * @alias listen
60.
	 * @param {Number} (port) The port that the server will use.
61.
	 * @return {Promise} This function will return a promise.
62.
	 * @function start
63.
	 */
64.
	start(port) {
65.
		if(this.listening()) {
66.
			throw new Error("the server was already listening");
67.
		}
68.

			
69.
		if(port !== undefined && typeof port !== "number") {
70.
			throw new TypeError("the argument port must be a number");
71.
		}
72.

			
73.
		return this._cerus.promise(function(event) {
74.
			this._server.listen(port || this._port, function() {
75.
				event("started");
76.
			});
77.
		}.bind(this));
78.
	}
79.

			
80.
	listen(port) {
81.
		return this.start(port);
82.
	}
83.

			
84.
	/**
85.
	 * This function will stop the server. It can only be called if the server is already running. 
86.
	 * It'll also return a promise that calls the "stopped" event when the function has finished 
87.
	 * stopping the server.
88.
	 * @example
89.
	 * // with a server already running
90.
	 * cerus.server().stop(); // or cerus.server().end();
91.
	 * // -> stops the server
92.
	 * @summary Stops the server.
93.
	 * @alias end
94.
	 * @return {Promise} This function will return a promise.
95.
	 * @function stop
96.
	 */
97.
	stop() {
98.
		if(!this.listening()) {
99.
			throw new Error("the server never started listening");
100.
		}
101.

			
102.
		return this._cerus.promise(function(event) {
103.
			this._server.close(function() {
104.
				event("stopped");
105.
			});
106.
		}.bind(this));
107.
	}
108.

			
109.
	end() {
110.
		return this.stop();
111.
	}
112.

			
113.
	/**
114.
	 * This is a getter and setter for the port that will be used for the server. It is possible to
115.
	 * not use this port by supplying a port to the .start() function directly.
116.
	 * @summary The getter/setter for the server port.
117.
	 * @param {Number} (port) The new server port.
118.
	 * @return {Number} The server port.
119.
	 * @function port
120.
	 */
121.
	port(port) {
122.
		if(typeof port === "number") {
123.
			this._port = port;
124.
		}
125.

			
126.
		return this._port;
127.
	}
128.

			
129.
	/**
130.
	 * With this function you can listen for server events. It'll return a promise that is called 
131.
	 * on a number of events. The "error" event is called when there was an error in the server. It
132.
	 * is called with the error as parameter. The "close" event is called when the server was 
133.
	 * closed. The "listening" event is called when the server has started listening. The 
134.
	 * "connection" event is called when there was a new connection together with the new socket as
135.
	 * paramater.
136.
	 * @summary Returns a promise that is called on every event.
137.
	 * @return {Promise} This function will return a promise.
138.
	 * @function event
139.
	 */
140.
	event() {
141.
		return this._cerus.promise(function(event) {
142.
			this._server.on("error", function(error) {
143.
				event("error", error);
144.
			});
145.

			
146.
			this._server.on("close", function() {
147.
				event("close");
148.
			});
149.

			
150.
			this._server.on("listening", function() {
151.
				event("listening");
152.
			});
153.

			
154.
			this._server.on("connection", function(socket) {
155.
				event("connection", socket);
156.
			});
157.
		}.bind(this));
158.
	}
159.

			
160.
	/**
161.
	 * This function returns if the server is currently listening for requests. This means that 
162.
	 * this function returns if the server has started or if it's currently stopped.
163.
	 * @summary Returns if the server is listening.
164.
	 * @return {Boolean} If the server is listening.
165.
	 * @function listening
166.
	 */
167.
	listening() {
168.
		return this._server.listening;
169.
	}
170.

			
171.
	/**
172.
	 * This is a getter and setter for the maximum amount of headers that the server will accept in 
173.
	 * a HTTP request. The default maximum amount of headers is 2000.
174.
	 * @summary The getter/setter for the maximum amount of headers.
175.
	 * @param {Number} (maxheaders) The new maximum amount of headers.
176.
	 * @return {Number} The maximum amount of headers.
177.
	 * @function maxheaders
178.
	 */
179.
	maxheaders(maxheaders) {
180.
		if(typeof maxheaders === "number") {
181.
			this._server.maxHeadersCount = maxheaders;
182.
		}
183.

			
184.
		return this._server.maxHeadersCount;
185.
	}
186.

			
187.
	/**
188.
	 * This is a getter and setter for the maximum amount of connections that the server will accept 
189.
	 * before refusing requests. By default there is no maximum amount of connections.
190.
	 * @summary The getter/setter for the maximum amount of connections.
191.
	 * @param {Number} (maxconnections) The new maximum amount of connections.
192.
	 * @return {Number} The maximum amount of connections.
193.
	 * @function maxconnections
194.
	 */
195.
	maxconnections(maxconnections) {
196.
		if(typeof maxconnections === "number") {
197.
			this._server.maxConnections = maxconnections;
198.
		}
199.

			
200.
		return this._server.maxConnections;
201.
	}
202.

			
203.
	/**
204.
	 * This function will return the current amount of connections. The connections will be 
205.
	 * returned using a promise. The amount of connections will be a parameter in the connections 
206.
	 * event. The amount of connections can only be fetched if the server is listening.
207.
	 * @summary Returns the amount of active connections.
208.
	 * @return {Number} The amount of connections.
209.
	 * @function connections
210.
	 */
211.
	connections() {
212.
		if(!this.listening()) {
213.
			throw new Error("the server hasn't started listening");
214.
		}
215.
		
216.
		return this._cerus.promise(function(event) {
217.
			this._server.getConnections(function(err, count) {
218.
				
219.
				if(err) {
220.
					event("error");
221.
				}
222.
				else {
223.
					event("connections", count);
224.
				}
225.
			});
226.
		}.bind(this));
227.
	}
228.

			
229.
	/**
230.
	 * This is a getter and setter for the number of milliseconds of inactivity the server needs to 
231.
	 * wait for incoming data. If it takes more than the alive time the request is presumed 
232.
	 * inactive. The default time is 5000 milliseconds (5 seconds).
233.
	 * @summary The getter/setter for the keep alive timeout time.
234.
	 * @param {Number} (alive) The keep alive timeout time.
235.
	 * @return {Number} The keep alive timeout time.
236.
	 * @function alive
237.
	 */
238.
	alive(alive) {
239.
		if(typeof alive === "number") {
240.
			this._server.keepAliveTimeout = alive;
241.
		}
242.

			
243.
		return this._server.keepAliveTimeout;
244.
	}
245.

			
246.
	/**
247.
	 * This is a getter and setter for the number of milliseconds of inactivity a socket can use 
248.
	 * before being presumed to have timed out. When a socket is presumed to have timed out the 
249.
	 * connection is destroyed. The default time 120000 (2 minutes).
250.
	 * @summary The getter/setter for the timeout time.
251.
	 * @param {Number} (timeout) The timeout time.
252.
	 * @return {Number} The timeout time.
253.
	 * @function timeout
254.
	 */
255.
	timeout(timeout) {
256.
		if(typeof timeout === "number") {
257.
			this._server.setTimeout(timeout);
258.
		}
259.

			
260.
		return this._server.timeout;
261.
	}
262.

			
263.
	/**
264.
	 * This function will return the address class for this server. The address class contains 
265.
	 * information about the address the server is using. This class can only be returned of the 
266.
	 * server is listening.
267.
	 * @summary Returns the server.address class.
268.
	 * @return {Class} The server.address class.
269.
	 * @function address
270.
	 */
271.
	address() {
272.
		if(!this.listening()) {
273.
			throw new Error("the server never started listening");
274.
		}
275.

			
276.
		if(this._address === undefined) {
277.
			this._address = new address(this._server);
278.
		}
279.

			
280.
		return this._address;
281.
	}
282.
}
283.

			
284.
module.exports = server;
285.

			
286.
/**
287.
 * This is the address class for the server. It contains information about the server, like the 
288.
 * port and ip address.
289.
 * @class server.address
290.
 */
291.
class address {
292.
	constructor(server) {
293.
		this._address = server.address();
294.
	}
295.

			
296.
	/**
297.
	 * This function will return the port the server is currently listening on.
298.
	 * @summary Returns the port the server is using.
299.
	 * @return {Number} The port the server is using.
300.
	 * @function port
301.
	 */
302.
	port() {
303.
		return this._address.port;
304.
	}
305.

			
306.
	/**
307.
	 * This function will return if the ip the server is currently using is IPv4 or IPv6.
308.
	 * @summary Returns the family of the server's ip.
309.
	 * @return {String} The family of the server's ip.
310.
	 * @function family
311.
	 */
312.
	family() {
313.
		return this._address.family;
314.
	}
315.

			
316.
	/**
317.
	 * This function will return the ip the server is currently using.
318.
	 * @summary Returns the ip of the server.
319.
	 * @return {String} The ip of the server.
320.
	 * @function address
321.
	 */
322.
	address() {
323.
		return this._address.address;
324.
	}
325.
}
326.