Creating a server with Node.js
Creating a server object
To create a server, you need an http / https object that is built into the core node.js and we can import it as a module. There are two module options:
http-Http is one of the built-in modules that comes with Node.js and allows you to create a server to accept requests from the client and return responses
https -Https module includes all the basic features of http, but with additional options for handling the necessary security differences such as certificates.
When we import one of these two modules, it will return the “http / https” object to us, as in the following example:
const http = require(‘http’);
Now that we have an http object, we will use it to create a server using the createServer () method:
const server = http.createServer()
In order for the server to start “listening” to the request, we have to start it, this is done by calling the listen () method:
listen(port, hostname, backlog, callback)
The listen () method accepts four optional parameters, and we will use only the first parameter that defines the port:
const http = require(‘http’);
const server = http.createServer()
server.listen(3000);
The request to the server is sent from this address “http: // localhost: 3000”. To stop the server we can use its method close ().
Callback to respond to the request of the so-called. requestListener ()
In the previous example, a server was created, but it does not have any functionality, in order for this server to respond to a request, it is necessary to create an event lister that will listen for requests to the server. We can do this on the standard so-called. event-based mode with on () method:
const http = require(‘http’);
const server = http.createServer()
server.on(“request”, (request, response) => {
// handle requests
})
server.listen(3000);
However, this approach is usually not used (although it is completely valid), but the createServer () method is passed as a parameter to the function (so-called requestListener ()) that responds to the request and which automatically adds a “request” event.
const http = require(‘http’);
const requestListener = function(request, response) {
// handle requests
}
const server = http.createServer(requestListener);
server.listen(3000);
for simplicity it is best to use the anonymous function:
const http = require(‘http’);
const server = http.createServer(function(request, response) {
// handle requests
});
server.listen(3000);
Acceptance of the GET request and response
Acceptance of the request
With the request, a request object is sent to the server and we can access it through the “request” parameter. It is a fairly “large” object that carries a lot of information in its properties and methods, so we can use them for the content of the response body (eg method, url, headers properties):
const http = require(‘http’);
const server = http.createServer((request, response) => {
let headers = request.headers;
let method = request.method;
let url = request.url;
if (method === “GET” && url === “/”) {
console.log(request.url + “\n”);
console.log(request.headers + “\n”);
console.log(request);
//hendle some response
}
}
)
server.listen(3000);
Parsing query from url
If the sender’s request is specific, it will pass it through the url (eg http: // host: 8000/?Name=Alen), so it is necessary to parse the url and extract data from it. We will use the node.js module “url” for parsing.
var http = require(‘http’);
var url = require(‘url’);
var server = http.createServer((request, response) => {
var queryData = url.parse(request.url, true).query;
// if there is a variable “name” in the url (eg http://host: 8000/?name = Alen)
// we can extract it from the url and use it later in the server response:
var nameFromRequest= queryData.name;
});
server.listen(3000);
Server response
a) API based response
To create a basic response, we will use the properties of the response objects: statusCode and its methods: setHeader (), write () and end ():
response.statusCode = 200
response.setHeader(“Content-Type”, “application/json”)
response.write(“some body content”)
response.end()
To respond to the server, we can use some of the data we get from the request object:
// Url request= http://localhost:3000/"
const http = require(‘http’);
const server = http.createServer((request, response) => {
let headers = request.headers;
let method = request.method;
let url = request.url;
const responseBody = {
headers,
method,
url,
body: [“item1”, “item2”, “item3”]
}
if (method === “GET” && url === “/”) {
response.statusCode = 200
response.setHeader(“Content-Type”, “application/json”)
response.write(JSON.stringify(responseBody))
response.end()
}
}
)
server.listen(3000);
b) HTML response
In previous examples, the responses were so-called. “API based”, but if we want to return html then we will do it similar to the following example:
// Url Request= http://localhost:3000/"
const http = require(‘http’);
const server = http.createServer((request, response) => {
const { method, url } = request
if (method === “GET” && url === “/”) {
response.setHeader(“Content-Type”, “text/html”)
response.statusCode = 200
response.end(
`<!doctype html>
<html>
<body>
<h2>This is the title</h2>
<p>This is some text</p>
</body>
</html>`
)
}
}
)
server.listen(3000);
If in the previous example the sender with which the sender sends a request is of the type http: //localhost:3000/?Name=Alen, then the sender will receive the answer “Hello Alen”, otherwise he will receive the answer “Hello World”.
Receiving data sent with the POST / PUT method
In addition to the get method, which visibly sends data within the url, we can “invisibly” send data to the server if we use the POST method. This method is usually used when sending the collected data from the form. In this example, we will generate the form on the server when the client sends a request for a page with the url: http: // localhost: 3000:
const http = require(‘http’);
const server = http.createServer((request, response) => {
const { method, url } = request
if (method === “GET” && url===”/”) {
response.setHeader(“Content-Type”, “text/html”)
response.statusCode = 200
response.end(`<!doctype html>
<html>
<body>
<form action=”/message” method=”post”>
<input type=”text” name=”fname” /><br />
<input type=”number” name=”age” /><br />
<input type=”file” name=”photo” /><br />
<button>Save</button>
</form>
</body>
</html>
`)
}
}
)
server.listen(3000);
When the user enters the data into the form and clicks on the “Save” button, due to the defined HTML attribute “action”, the data from the form will be sent to the page with the url / message, and a new request will be created to forward the data. The data collected from the form is sent as “readable streams” and can look like this:
localefname=Somename&age=15&photo=picture_name.png
What are STREAMS?
Streams are a way to efficiently handle any type of information exchange (it is also used for reading / writing files, network communication…). Streams is not only a concept unique to Node.js, but has existed within the Unix operating system for decades. Unlike the traditional way where the whole file is loaded into memory and then processed, here, when using streams, the program reads part by piece of data and processes it simultaneously, thus not loading the memory at all. In addition to the mentioned advantage where memory is used efficiently because you do not need to load large amounts of data into memory to be able to process them, there is another advantage of the so-called. “Time efficiency” which reduces the time required to start processing data, because you can start processing as soon as you get some of the data, instead of waiting for all the data to be available. There are three types of streams:
“Writable stream” (allow node.js to transfer data to a stream)
“Readable stream” (allows node.js to read data from the stream)
“Duplex” (allows node.js to both write and read stream)
To know when the data is being sent and when the data transfer is completed there are registered events for it. “Readable streams” have the following types of events registered:
data (this event is broadcast whenever the stream passes a piece of data called “chunk”)
end (this event is broadcast whenever the stream has no more data to pass)
error
close
readable
In the following example, we will log in to the “data” event to notify when the data is being sent, and in order to know when the message ends, we must also log in to the “end” event:
if (req.method === ‘POST’ && url===”/message”) {
let body = ‘’;
req.on(‘data’, chunk => {
// convert Buffer chunk to string
body += chunk.toString();
});
req.on(‘end’, () => {
console.log(body);
res.end(‘We have downloaded your submitted data’);
});
}
The variable body could look like this after receiving the data:
fname=someName&age=15&photo=picture_Name.png
When we have data in this form, we need to parse it, and for that we will use the node.js module “querystring” and its method parse (), which will transfer the data in this form to the collection of “key / value” pairs:
const { parse } = require(‘querystring’);
if (req.method === ‘POST’) {
let body = ‘’;
req.on(‘data’, chunk => {
body += chunk.toString();
});
req.on(‘end’, () => {
console.log(
parse(body)
);
res.end(‘We have downloaded your submitted data’);
});
}
The code that is now legible to us will be printed in the console:
{
fname: ‘someName’,
age: ‘15’,
photo: ‘picture_Name.png’
}