Deno vs Node.js: Native HTTP clients
This article is a part of the equivalent series that provide Deno’s equivalent of commonly used functionality provided by Node.js.
In this article, we’ll compare how native HTTP clients are used in Deno (using fetch) & Node.js (using http.request).
Imports
- In Node.js, an import from core http module is required
- In Deno, no import is required as http client is a part of the core runtime (except for streaming files)
// ==> Node.js
const http=require('http');
const {request}=require('http'); //alternative// ==> Deno
no imports
Type
- In Node.js, HTTP request/response handling is through callbacks
- In Deno, HTTP request/response handling is through promises
// ===> Node.js
request(options, ()=>{});// ===> Deno
await fetch(options);
Basic request
- In Node.js, a basic HTTP request can be sent through the request API that returns the response through a callback function
- In Deno, a basic HTTP request can be sent through the async fetch API
// ==> Node.js
const {request}=require('http');
const req={
hostname: 'goweather.herokuapp.com',
path: '/weather/sacramento'
};
request(req, res=>{})).end();// ==> Deno
const res=await fetch('http://goweather.herokuapp.com/weather/sacramento');
Response status & headers
- In Node.js, statusCode, statusMessage & headers contains the response data (not the body)
- In Deno, status, statusText & headers contains the response data (not the body)
// ==> Node.js
res.statusCode; //200
res.statusMessage; //OK
res.headers; //{
server: 'Cowboy',
connection: 'close',
'content-type': 'application/json',
date: 'Thu, 07 Oct 2021 17:38:07 GMT',
'content-length': '229',
via: '1.1 vegur'
}// ==> Deno
res.status; //200
res.statusText: //OK
res.headers: //Headers {
connection: "keep-alive",
"content-length": "229",
"content-type": "application/json",
date: "Thu, 07 Oct 2021 17:40:31 GMT",
server: "Cowboy",
via: "1.1 vegur"
},
- In Node.js, response headers can be accessed directly via dot notation
- In Deno, response headers need to be accessed through get function
// ==> Node.js
res.headers.date; //Thu, 07 Oct 2021 18:01:49 GMT// ==> Deno
res.headers.get('date'); //Thu, 07 Oct 2021 18:02:31 GMT
Receiving body
- In Node.js, response body needs to be collected through ‘data’ callbacks (multiple callbacks are possible)
- In Deno, response body is collected by the API (no work on user)
// ==> Node.js
request(opts, r=>{
let s='';
r.on('data', c=>s+=c);
r.on('end', () => console.log(s))
}).end();//{"temperature":"14 °C","wind":"15 km/h","description":"Sunny","forecast":[{"day":"1","temperature":"20 °C","wind":"17 km/h"},{"day":"2","temperature":"18 °C","wind":"15 km/h"},{"day":"3","temperature":"4 °C","wind":" km/h"}]}// ==> Deno
const res=await fetch('http://goweather.herokuapp.com/weather/sacramento');
const s=await res.text();//{"temperature":"14 °C","wind":"15 km/h","description":"Sunny","forecast":[{"day":"1","temperature":"20 °C","wind":"17 km/h"},{"day":"2","temperature":"18 °C","wind":"15 km/h"},{"day":"3","temperature":"4 °C","wind":" km/h"}]}
Sending simple body
- In Node.js, body can be sent through write API call (string or buffer)
- In Deno, body can be sent through body attribute (string, form data, url search params, stream, blob, etc.)
// ===> Node.js
const {request}=require('http');
const opts={
hostname: 'postman-echo.com',
path: '/post',
method: 'POST',
headers: {
'content-type': 'text/plain'
}
};
const req=request(opts, ()=>{});
req.write('Hello!');
req.end();// ===> Deno
const res=await fetch('http://postman-echo.com/post', {
method: 'POST',
body: 'Hello!',
headers: {
'content-type': 'text/plain'
}
});
JSON handling
- In Node.js, JSON encoding/decoding needs to be done by the user
- In Deno, JSON encoding needs to be done by the user while JSON decoding is through API
// ==> Node.js
const {request}=require('http');
const opts={
hostname: 'postman-echo.com',
path: '/post',
method: 'POST',
headers: {
'content-type': 'application/json'
}
};
const cb=res=>{
let s='';
res.on('data', c=>s+=c);
res.on('end', () => console.log(JSON.parse(s).data))
};
const req=request(opts, cb);
req.write(JSON.stringify({a: 1, b: 2}));
req.end();//s.data => { a: 1, b: 2 }// ==> Deno
const res=await fetch('http://postman-echo.com/post', {
method: 'POST',
body: JSON.stringify({a: 1, b: 2}),
headers: {
'content-type': 'application/json'
}
});
const s=await res.json();
console.log(s.data);//s.data => { a: 1, b: 2 }
File upload
- In Node.js, a file stream can be prepared & piped directly to the http request object
- In Deno, a file stream needs to be prepared using standard library’s readableStreamFromReader function, then given to the body attribute
// ===> Node.js
const {request}=require('http');
const fs=require('fs');
const opts={
hostname: 'postman-echo.com',
path: '/post',
method: 'POST',
headers: {
'content-type': 'text/plain'
}
};
const cb=res=>{
let s='';
res.on('data', c=>s+=c);
res.on('end', () => console.log(JSON.parse(s).data))
};
const req=request(opts, cb);
const stream=fs.createReadStream('./testdata/sample.txt');
stream.pipe(req);
stream.on('end', () => req.end());//s.data => Learning Deno Is Fun!// ===> Deno
import {readableStreamFromReader as toStream} from "https://deno.land/std/io/mod.ts";
const res=await fetch('http://postman-echo.com/post', {
method: 'POST',
body: toStream(await Deno.open('./testdata/sample.txt')),
headers: {
'content-type': 'text/plain'
}
});
const s=await res.json();
console.log(s.data);//s.data => Learning Deno Is Fun!
URL encoded body
- In Node.js, URLSearchParams can be used to create a URL encoded body & then converted to string for the write API
- In Deno, URLSearchParams can also be used to create a URL encoded body & given directly to the body attribute
// ===> Node.js
const opts={
hostname: 'postman-echo.com',
path: '/post',
method: 'POST',
headers: {
'content-type': 'x-www-form-urlencoded'
}
};
const req=request(opts, cb);
const params=new URLSearchParams({
a: 1,
b: "hello"
});
req.write(params.toString());
req.end();// ===> Deno
const params=new URLSearchParams({
a: '1',
b: 'hello'
});
const res=await fetch('http://postman-echo.com/post', {
method: 'POST',
body: params,
headers: {
'content-type': 'x-www-form-urlencoded'
}
});
This story is a part of the exclusive medium publication on Deno: Deno World.