PROWAREtech
NodeJS: Create HTTP Server
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.
NOTE: this is a very simple example without file I/O. For a more complex example see: Enable CORS on a Node.js Server
Code Examples
Create a file named index.js, app.js or server.js in the project directory.
const html =
`
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
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 type="text/javascript">
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`);
}
});