Node.JS has built-in `http` module, which allows Node.JS to communicate over HyperText Transfer Protocol (HTTP).
To include that module, we use `require()` method:
var http = require("http");
## "Hello, World" server
In this example, the server sends "Hello, World" response. This server is listening at port 8080:
{% codeblock server.js lang:javascript %}
//Hello World server
var http = require("http");
var port = 8080;
var server = http.createServer(function (req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/plain"
});
res.write("Hello, World!");
res.end();
});
server.listen(port, function() {
console.log("Started server at port " + port + ".");
});
{% endcodeblock %}
For creating HTTP server object we use `http.createServer()` method. Server will then listen at port 8080. This server writes header indicating, that we're sending plain text. Then it sends "Hello, World" message and ends the connection.
Save the code above in a file called *server.js* and start the server using `node server.js`.
If you visit *localhost:8080* in your web browser, the result will look like this:
![Hello World server](/images/hello-server.png)
## Serving files using Node.JS
For reading files, we're using `fs` module and `fs.readFile()` method.
The code will look like this:
{% codeblock server.js lang:javascript %}
//Serving index...
var http = require("http");
var fs = require("fs");
var port = 8080;
var server = http.createServer(function (req, res) {
fs.readFile("index.html", function(err, data) {
if(err) {
res.writeHead(500, "Internal Server Error", {
"Content-Type": "text/plain"
});
res.end("500 Internal Server Error! Reason: " + err.message);
} else {
res.writeHead(200, "OK", {
"Content-Type": "text/html"
});
res.end(data);
}
});
});
server.listen(port, function() {
console.log("Started server at port " + port + ".");
});
{% endcodeblock %}
This code will serve *index.html* file, and returns 500 error if there was a problem reading that file.
But what if that index file doesn't exist? We will then need to serve 404 error page:
{% codeblock server.js lang:javascript %}
//Serving 404...
var http = require("http");
var fs = require("fs");
var port = 8080;
var server = http.createServer(function (req, res) {
fs.readFile("index.html", function(err, data) {
if(err) {
if(err.code == "ENOENT") {
//ENOENT means "File doesn't exist"
res.writeHead(404, "Not Found", {
"Content-Type": "text/plain"
});
res.end("404 Not Found");
} else {
res.writeHead(500, "Internal Server Error", {
"Content-Type": "text/plain"
});
res.end("500 Internal Server Error! Reason: " + err.message);
}
} else {
res.writeHead(200, "OK", {
"Content-Type": "text/html"
});
res.end(data);
}
});
});
server.listen(port, function() {
console.log("Started server at port " + port + ".");
But we have introduced path traversal vulnerability (being able to access file outside the web root)! To mitigate that, we'll use a regular expression, that removes all dot-dot-slash sequences from file name:
res.end("500 Internal Server Error! Reason: " + err.message);
}
} else {
res.writeHead(200, "OK", {
"Content-Type": "text/html"
});
res.end(data);
}
});
});
server.listen(port, function() {
console.log("Started server at port " + port + ".");
});
{% endcodeblock %}
That might work fine for HTML files, but if you try other files, there will be content type mismatch. To get MIME types, we use `mime-types` package, that you can install using `npm install mime-types`. We will then use that module, along with `path` module to get file extension. The code will look like this:
{% codeblock server.js lang:javascript %}
//Adding MIME type support...
var http = require("http");
var fs = require("fs");
var mime = require("mime-types");
var path = require("path");
var port = 8080;
var server = http.createServer(function (req, res) {
res.end("500 Internal Server Error! Reason: " + err.message);
}
} else {
res.writeHead(200, "OK", {
"Content-Type": mime.lookup(ext) || undefined
});
res.end(data);
}
});
});
server.listen(port, function() {
console.log("Started server at port " + port + ".");
});
{% endcodeblock %}
We have now very simple HTTP static server, serving at *localhost:8080*.
**Wait... Did we forget about [SVR.JS](https://svrjs.duckdns.org)?** SVR.JS is a web server running on Node.JS, that supports not only static file serving, but also directory listings, path rewriting, complete URL sanitation, HTTPS, HTTP/2.0, expandability via mods and server-side JavaScript, and it's configurable.