Making HTTP requests with Node
By Flavio Copes
Learn how to perform HTTP requests in Node.js with the built-in https module, covering GET, POST, PUT, and DELETE using https.request() and options.
You can make HTTP requests in Node.js with the built-in https module, no external library needed. You describe the request in an options object, pass it to https.request(), and read the response as it streams in.
I use the term HTTP, but HTTPS is what should be used everywhere, therefore these examples use HTTPS instead of HTTP.
Perform a GET Request
The options object holds the pieces of the request: the host, the port (443 for HTTPS), the path, and the HTTP method:
const https = require('https')
const options = {
hostname: 'flaviocopes.com',
port: 443,
path: '/todos',
method: 'GET'
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.end()
A few things to notice here.
The callback receives the response object res before the body has arrived. The body comes in as a stream, in chunks, through the data events. That’s why we write each chunk as it arrives instead of logging one big string.
The error handler is not optional in practice. If the DNS lookup fails or the server refuses the connection, and no error listener is attached, Node crashes the whole process.
And don’t forget req.end(). The request is not actually sent until you call it. Forget it and the program hangs, waiting forever.
Perform a POST Request
A POST works the same way, with two additions: headers describing the body, and the body itself written with req.write():
const https = require('https')
const data = JSON.stringify({
todo: 'Buy the milk'
})
const options = {
hostname: 'flaviocopes.com',
port: 443,
path: '/todos',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.write(data)
req.end()
Be careful with Content-Length. Here data.length works because the string is plain ASCII. But .length counts characters, not bytes, and the header needs bytes. Send 'Comprare il caffè' and the two numbers differ, because è takes 2 bytes in UTF-8. The safe version is:
'Content-Length': Buffer.byteLength(data)
Use Buffer.byteLength() any time the body might contain accented letters, emoji, or any non-ASCII text.
PUT and DELETE
PUT and DELETE requests use the same POST request format, and just change the options.method value.
If you want to try these requests from the command line first, I made a free route to curl tool that builds the curl command for you.
Related posts about node: