Raw Node.js - HTTP Server Basics (How To Do It Without NPM Express Framework)

This article will try to make the reader familiar with the Node.js HTTP server module. It will not rely upon NPM Express. If not familiar with JavaScript then read this tutorial which covers a version of JavaScript compatible with most Internet browsers. If not familiar with Node.js then read this tutorial which covers installing Node.js, Express.js and more.

In the following code examples, a basic HTTP server will be implemented and then it will parse form data posted by an AJAX request. This code is compatible with browsers IE10 and newer.

Code Examples

Create a file named index.js, app.js or server.js in the project directory.

const html =
`
<!DOCTYPE html>
<html>
<head>
	<script>
	function submitForm(form) {
		var x = new XMLHttpRequest();
		x.onreadystatechange = function(){
			if(x.readyState == 4 && x.status == 200) {
				var obj = JSON.parse(x.responseText);
				var people = document.getElementById("people");
				people.innerText = "";
				for(var i = 0; i < obj.length; i++) {
					people.innerText += obj[i].lastname + ", " + obj[i].firstname + "\\r\\n";
				}
			}
		};
		x.open("post", "/", true);
		x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
		x.send("firstname=" + encodeURIComponent(form.firstname.value) + "&lastname=" + encodeURIComponent(form.lastname.value));
		return false;
	}
	</script>
</head>
<body>
	<pre id="people"></pre>
	<form action="/" method="post" onsubmit="return submitForm(this);">
		<input type="text" name="firstname" placeholder="first name" />
		<input type="text" name="lastname" placeholder="last name" />
		<input type="submit" />
	</form>
</body>
</html>
`;

const http = require("http");
const server = http.createServer().listen(8000);
console.log("listening on port 8000");

server.on("request", function (request, response) {
	if(request.url != "/") {
		// ONLY ALLOW "/"
		response.writeHead(404, {"Content-Type":"text/plain"})
		response.end(`path ${request.url} not found`);
		return;
	}
	if (request.method == "POST") {
		// READ THE POST BODY AND PARSE THE DATA (see code example #2)
		response.writeHead(200, {"Content-Type":"application/json"})
		response.end("[]");
	}
	else if (request.method == "GET") {
		response.writeHead(200, {"Content-Type":"text/html"})
		response.end(html);
	}
	else {
		response.writeHead(405, {"Content-Type":"text/plain"})
		response.end(`method ${request.method} not allowed`);
		
	}
});

Now, the code with the POST request processsing completed. It is an incredibly small amount of code to do this much work. To do this in C/C++ would be much more work.

const html =
`
<!DOCTYPE html>
<html>
<head>
	<script>
	function submitForm(form) {
		var x = new XMLHttpRequest();
		x.onreadystatechange = function(){
			if(x.readyState == 4 && x.status == 200) {
				var obj = JSON.parse(x.responseText);
				var people = document.getElementById("people");
				people.innerText = "";
				for(var i = 0; i < obj.length; i++) {
					people.innerText += obj[i].lastname + ", " + obj[i].firstname + "\\r\\n";
				}
			}
		};
		x.open("post", "/", true);
		x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
		x.send("firstname=" + encodeURIComponent(form.firstname.value) + "&lastname=" + encodeURIComponent(form.lastname.value));
		return false;
	}
	</script>
</head>
<body>
	<pre id="people"></pre>
	<form action="/" method="post" onsubmit="return submitForm(this);">
		<input type="text" name="firstname" placeholder="first name" />
		<input type="text" name="lastname" placeholder="last name" />
		<input type="submit" />
	</form>
</body>
</html>
`;

const http = require("http");
const server = http.createServer().listen(8000);
console.log("listening on port 8000");

var people = new Array();

server.on("request", function (request, response) {
	if(request.url != "/") {
		response.writeHead(404, {"Content-Type":"text/plain"})
		response.end(`path ${request.url} not found`);
		return;
	}
	if (request.method == "POST") {
		var body = "";
		request.on("data", function (data) {
			body += data.toString();
		});
		request.on("end", function () {
			// COULD USE "querystring" MODULE INSTEAD OF PARSING IT HERE
			var bodyArray = body.split('&');
			var person = {};
			for(var i = 0; i < bodyArray.length; i++) {
				var temp = bodyArray[i].split('=');
				if(temp.length == 2)
					person[temp[0]] = decodeURIComponent(temp[1].replace(/\+/g, "%20"));
				else
					person[temp[0]] = null;
			}
			people[people.length] = person;
			people.sort(function(obj1, obj2) {
				if(obj1.lastname == obj2.lastname) {
					if(obj1.firstname < obj2.firstname) return -1;
					if(obj1.firstname > obj2.firstname) return 1;
					return 0;
				}
				if(obj1.lastname < obj2.lastname) return -1;
				if(obj1.lastname > obj2.lastname) return 1;
				return 0;
			});
			response.writeHead(200, {"Content-Type":"application/json"})
			response.write(JSON.stringify(people));
			response.end();
		});
	}
	else if (request.method == "GET") {
		// MORE WORK NEEDS TO BE DONE SUCH AS SENDING ALL THE APPROPRIATE HEADERS, BUT THIS COVERS THE BASICS
		response.writeHead(200, {"Content-Type":"text/html"})
		response.end(html);
	}
	else {
		response.writeHead(405, {"Content-Type":"text/plain"})
		response.end(`method ${request.method} not allowed`);
		
	}
});

Coding Video

https://youtu.be/Fcu6W33z_lA