HTTP client in JavaScript: making requests correctly — from A to Z
In modern web development, interacting with external APIs and servers is a basic task. Whether it's fetching weather data, submitting a form, or integrating with a payment gateway, you will need an HTTP client. In this article, we will break down how to create HTTP requests in JavaScript (Node.js) correctly: from choosing a tool to error handling and optimization. You will learn how to write reliable and performant code.
1. Choosing a tool: native capabilities vs libraries
Node.js provides several ways to make HTTP requests. The choice depends on the complexity of the task and personal preferences.
1.1. Built-in http / https module
This is the lowest-level approach. It gives you full control but requires a lot of code for simple requests.
const https = require('https');
function getUsers() { return new Promise((resolve, reject) => { const url = 'https://jsonplaceholder.typicode.com/users'; https.get(url, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { resolve(JSON.parse(data)); } catch (e) { reject(e); } }); }).on('error', reject); });}
getUsers().then(console.log).catch(console.error);1.2. Global fetch (with Node.js 18+)
Starting from version 18, Node.js has a native fetch, familiar from browsers. This is a modern and convenient API.
async function getPosts() { try { const response = await fetch('https://jsonplaceholder.typicode.com/posts'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error('Fetch error:', error); throw error; }}
getPosts().then(posts => console.log(posts.slice(0, 2)));1.3. Popular libraries: axios
axios is the most popular library for HTTP requests. It provides a convenient API, promise support, interceptors, and automatic JSON parsing.
const axios = require('axios');
async function createTodo() { try { const response = await axios.post('https://jsonplaceholder.typicode.com/todos', { title: 'Learn HTTP clients', completed: false, userId: 1 }); console.log('Created:', response.data); return response.data; } catch (error) { console.error('Error:', error.response?.data || error.message); }}
createTodo();Summary: For simple scripts, use fetch. For serious projects with many requests and interceptors, use axios. Leave the http module for specific cases.
2. Main request types and working with data
Let's break down how to correctly send GET, POST, PUT, and DELETE requests using axios.
2.1. GET — retrieving data
async function getUser(id) { try { const { data } = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`); return data; } catch (error) { throw new Error(`Failed to get user ${id}: ${error.message}`); }}2.2. POST — creating a resource
Pass data in the request body. It is important to specify the content type (Content-Type). Axios does this automatically for JSON.
async function createUser(userData) { const response = await axios.post('https://jsonplaceholder.typicode.com/users', userData, { headers: { 'Content-Type': 'application/json' } }); return response.data;}2.3. PUT and PATCH — updating
PUT repla