Node.js Native HTTP Request: Get & Post
In this article, we’ll explore how to perform GET and POST requests using Node.js’s native http module, with practical examples leveraging the JSONPlaceholder API, a free online REST API for testing and prototyping.
Why It Matters
Using Node.js’s native http module for HTTP requests is valuable because:
- No external dependencies: Keeps your project lightweight.
- Educational value: Deepens understanding of how HTTP requests work under the hood.
- Control: Fine-grained control over request options and handling.
While higher-level libraries simplify common tasks, knowing how to use the core modules ensures you understand the fundamentals and can troubleshoot issues effectively.
Core Concepts
The http Module
Node.js’s http module provides methods to create HTTP clients and servers. For client-side requests, it offers the http.request() method, which allows you to craft detailed requests, including method, headers, and payloads.
Key Components
- Request options: Host, port, path, method, headers.
- Request object: Writable stream to send data.
- Response object: Readable stream to receive data.
Code Walkthrough
Let’s walk through examples of GET and POST requests with detailed inline comments.
1. Performing a GET Request
We’ll fetch a list of posts from JSONPlaceholder.
const http = require('http');
// Define the options for the GET request
const options = {
hostname: 'jsonplaceholder.typicode.com', // API host
port: 80, // Default HTTP port
path: '/posts', // API endpoint
method: 'GET', // HTTP method
headers: {
'Content-Type': 'application/json' // Expect JSON response
}
};
// Make the GET request
const req = http.request(options, (res) => {
let data = '';
// Concatenate chunks of data as they arrive
res.on('data', (chunk) => {
data += chunk;
});
// When the response ends, parse and log the data
res.on('end', () => {
try {
const posts = JSON.parse(data);
console.log('Fetched posts:', posts);
} catch (error) {
console.error('Error parsing JSON:', error);
}
});
});
// Handle request errors
req.on('error', (error) => {
console.error('Request error:', error);
});
// End the request (for GET, no body is sent)
req.end();
Note: For HTTPS requests, you’d use the https module instead.
2. Performing a POST Request
Suppose we want to create a new post.
const http = require('http');
// Data to send in the POST request
const postData = JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1
});
// Define request options
const options = {
hostname: 'jsonplaceholder.typicode.com',
port: 80,
path: '/posts',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData) // Required for POST
}
};
// Make the POST request
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const responsePost = JSON.parse(data);
console.log('Response from POST:', responsePost);
} catch (error) {
console.error('Error parsing response JSON:', error);
}
});
});
req.on('error', (error) => {
console.error('Request error:', error);
});
// Write data to request body
req.write(postData);
// End request
req.end();
Common Mistakes
- Forgetting to call
req.end(): The request won’t be sent without ending the request. - Incorrect headers or
Content-Length: Omitting or mismatching headers can cause server errors. - Using the wrong module for HTTPS: For secure requests, use
httpsinstead ofhttp. - Not handling asynchronous responses properly: Always listen to
'data'and'end'events to process responses. - Assuming JSON response without parsing: Always parse the response data to utilize it effectively.
Best Practices
- Use Promises or async/await: Encapsulate requests in functions returning Promises for cleaner asynchronous code.
- Handle errors gracefully: Always listen for
'error'events. - Use
httpsmodule for secure endpoints: JSONPlaceholder can be accessed via HTTPS (https://jsonplaceholder.typicode.com). - Set appropriate headers: Especially
Content-TypeandContent-Lengthfor POST/PUT requests. - Abstract repetitive code: Create reusable functions for GET and POST requests.
Here’s a quick example of wrapping GET requests in a Promise:
const http = require('http');
function httpGet(hostname, path) {
return new Promise((resolve, reject) => {
const options = {
hostname,
port: 80,
path,
method: 'GET',
headers: { 'Accept': 'application/json' }
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => (data += chunk));
res.on('end', () => {
try {
resolve(JSON.parse(data));
} catch (err) {
reject(err);
}
});
});
req.on('error', reject);
req.end();
});
}
// Usage
httpGet('jsonplaceholder.typicode.com', '/posts')
.then(posts => console.log(posts))
.catch(error => console.error(error));
Final Thoughts
While third-party libraries like Axios or node-fetch simplify HTTP requests, mastering Node.js’s native http module provides you with a solid understanding of HTTP communication and greater control over your requests. With examples above, you can now confidently perform GET and POST requests in your Node.js applications, whether you’re building APIs, integrating services, or learning the fundamentals.
Remember: Always handle errors, set proper headers, and close your requests properly to ensure robust and reliable network communication.
References
- Node.js
httpmodule documentation - MDN Web Docs on HTTP
- JSONPlaceholder API
- Using Promises with Node.js HTTP requests
Happy coding!