Once you understand how you can manage incoming requests using the HTTP module, it's time to learn how to send requests using the same module. Sending requests is actually easier than creating a server, and all you need to do is create a well-structured options object in order to execute complex requests. This knowledge can come in handy for testing API services, backend solutions, or proxying frontend requests and adding new data to them in the future.
Server creation
Before you send requests to servers and see how each server responds, you need to create a server that can handle these requests. Let's make a server that listens on port 8081 and has only one endpoint — /animals. When a query is provided in a request, the server should return that query as a response. If the query is empty, it should generate a response with an array of animals to handle empty requests.
// Server creation code snippet
const http = require('node:http');
const url = require('node:url');
const port = 8081;
// Create a server that can handle your request at 'animals' endpoint
http.createServer((request, response) => {
if(url.parse(request.url).pathname === '/animals') {
response.writeHead(200, {'Content-Type': 'application/json'});
// Parse the request params in the query using URL module
const requestQueries = url.parse(request.url).query?.split('&') || [];
const requestParams = Object.fromEntries(requestQueries.map((query) => query.split('=')));
// Check that the request query is not empty to send back as a response to the request query
// Incase it is empty, it will return the "animals" array.
if(requestQueries.length) response.write(JSON.stringify(requestParams));
else response.write(JSON.stringify([
'cat', 'dog', 'bird', 'elephant'
]));
response.end();
};
}).listen(port);
You will need this code snippet to execute the code in all subsequent snippets. Remember to keep it in the context of all subsequent code snippets.
Sending requests
The http module can also send requests. To send requests, you can use http.request() method or http.get() method. The only difference between these two is that the .get() method automatically sets the GET request method and calls the .end() method. The following snippet uses .get() method, to quickly send a GET request to a local server hosted on your computer:
// Server creation code here...
http.get('http://localhost:8081/animals', (res) => {
let fullResponse = '';
res.on('data', (dataChunk) => { fullResponse += dataChunk; });
res.on('end', () => { console.log(JSON.parse(fullResponse)); });
});
Let's analyze what each line of the snippet does:
.get()— accepts a URL and a callback method as parameters. In the callback, you can handle the events that take place in a request's lifecycle.res.on('data', (dataChunk) => { fullResponse += dataChunk); });— Ondataevent, you can read response body chunks.res.on('end', () => { console.log(fullResponse) });— Runs after the request ends, so you can do something after the response is received.
Here is the console result of the code snippet above:
[ 'cat', 'dog', 'bird', 'elephant' ]
Next, let's look at the .request() method that allows you to pass options. In options, you can specify the hostname, port, path, method, and headers.
// Server creation code here...
// Pass the options and make a request
const options = {
hostname: 'localhost',
port: 8081,
path: '/animals',
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
http.request(options, (res) => {
let fullResponse = '';
res.on('data', (dataChunk) => { fullResponse += dataChunk; });
res.on('end', () => { console.log(JSON.parse(fullResponse)); });
}).end();
This code snippet will give the following result:
[ 'cat', 'dog', 'bird', 'elephant' ]
The code snippet above makes the same request as .get(). But let's take a look closer at each of options objects. hostname can be a URL or an IP address of the target host, path can contain query parameters if needed, and headers can be used to set any HTTP request header — for example, Content-Type to set the request data type, as provided in the example.
Passing query params
While handling query parameters using GET requests, you should know how to send that type of request using the HTTP module. Consider an example where you need to send your favorite drink to the API server:
const query = {
drink: 'coffee',
isNeedSugar: false,
type: 'batch brew'
};
To send it using query params, you have to transform the object to URL parameters. There are many ways to do so, but you can use a familiar URL module to do that — the URLSearchParams class. So the new options object will look like this:
const query = {
drink: 'coffee',
isNeedSugar: false,
type: 'batch brew'
};
const searchParams = new URLSearchParams(query).toString();
const options = {
hostname: 'localhost',
port: 8081,
path: '/animals?' + searchParams,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
It might be tricky to keep all these code snippets in mind. So here is the result code that contains the creation of request options with query parameters.
{ drink: 'coffee', isNeedSugar: 'false', type: 'batch+brew' }
Conclusion
The http module is a low-level tool to create an HTTP server that can handle incoming requests or send requests to other services. It can be helpful while testing front-end REST API-based applications. Express.js framework is also based on the http module and can help anyone create back-end services.