Request | Axios | SuperAgent | Node-Fetch | |
---|---|---|---|---|
NodeJS | + | + | + | + |
Browser | – | + | + | + |
API | Callback / Stream | Promise | Promise-compatible | Promise |
Query params | url / object | url / object | url / object | url |
Custom HTTP verbs | + | + | + | + |
Custom HTTP headers | + | + | + | + |
Default HTTP headers | Connection Host |
Accept Connection Host User-Agent |
Accept-Encoding Connection Host User-Agent |
Accept Accept-Encoding Connection Host User-Agent
|
HTTPS | + | + | + | + |
Forms | + | + | + | - |
Cookies | + | - | + | - |
Auto Redirect On | ++ | + | + | + |
Auto Redirect Off | TODO ? | TODO ? | TODO ? | TODO ? |
Basic auth (by default) | + | + | + | - |
All platforms are available as NPM packages.
- You can bundle Request but it's way too big (~2 Mib) for Browser (due to NodeJS Streams etc.).
- Node-Fetch just emulates native fetch API.
Supports callback and streaming APIs natively. There are external plugins for promise API.
Or just new Promise(...)
;)
TODO:
- 404 is an "error" or not?
- 500 is an "error" or not?
let opts = {
url: "https://httpbin.org/get",
qs: { id: 30 },
}
// callback
request.get(opts, (err, response, body) => {
if (err) {
console.log("err:", err)
}
else {
console.log("code:", response.statusCode) // : number
console.log("headers:", response.headers) // : Object
console.log("body:", body) // : TODO auto parsed due to mimetype?!
}
})
// streaming
request(opts).pipe(process.stdout)
TODO:
- 404 is an "error" or not?
- 500 is an "error" or not?
let opts = {
url: "https://httpbin.org/get",
params: { id: 30 },
}
axios.get(opts)
.then((res) => {
console.log("code:", res.status) // TODO type
console.log("headers:", res.headers) // TODO type
console.log("body:", res.data) // TODO type
})
.catch((err) => {
console.log(err.status)
})
TODO:
- 404 is an "error" or not?
- 500 is an "error" or not?
let url = "https://httpbin.org/get"
let opts = { id: 30 }
superagent.get(url)
.query(opts)
.end((err, res) => {
if (err) {
console.log("err:", err.status)
console.log("err:", err.response.error)
} else {
console.log(res.statusCode)
console.log(res.headers)
console.log(res.body)
}
})
TODO:
- 404 is an "error" or not?
- 500 is an "error" or not?
let url = "https://httpbin.org/get?id=30"
fetch(url)
.then(res => {
console.log(res.status)
console.log(res.headers)
return(res)
})
.then(res => res.json())
.then(res => {
console.log(res)
}).catch(err => {
console.log(error)
})
TODO demo
TODO demo
let opts = {
method: "move",
url: "https://httpbin.org/get",
qs: { id: 30 }
}
request(opts, (error, response, body) => {
//....
})
let opts = {
method: "move",
url: "https://httpbin.org/get",
params: { id: 30 }
}
axios(opts)
.then((res) => {
//...
}).catch((err) => {
//...
})
let method = "move"
let url = "https://httpbin.org/get"
let params = { id: 30 }
superagent(method, url)
.query(params)
.end(function(err, res) {
//...
})
let opts = { method: "move" }
let url = "https://httpbin.org/get?id=30"
fetch(url, opts)
.then(
//...
})
All four libraries support passing query params in URL.
Node-Fetch does not support query-as-object passing.
request
.post("https://httpbin.org/post", { form: { test: "test" } })
.pipe(process.stdout)
To perform post request with application/x-www-form-urlencoded
in Axios, we need to use querystring
or qs
const querystring = require("querystring")
axios
.post(endPoints.post.url, querystring.stringify({form: {test: "test"}}))
.then((res) => {
response(res)
})
.catch((err) => {
error(err)
})
By default SuperAgent user json
, and to use application/x-www-form-urlencoded
we need to invoke type()
, and pass "form" to it.
superagent
.post("https://httpbin.org/post")
.type("form")
.send({ test: "test"})
.end((err, res) => {
//....
})
To do the same in Node-Fetch we need to set headers manually, or use external libraries
fetch(endPoints.post.url, { method: "post",
headers: {"Content-Type": "application/x-www-form-urlencoded"},
body: "test=test" })
.then(
//....
)
Request adds Referer
header like:
Referer: http://httpbin.org/redirect-to?url=http://httpbin.org/get
...
There is no difference between normal get request, and redirected request.
Request and Axios have got similar API for BasicAuth:
let basicAuth = {
method: "get",
uri: "https://httpbin.org/basic-auth/user/passwd",
auth: {
user: "user",
pass: "passwd"
}
}
request(basicAuth, (error, response, body) => console.log(response.statusCode))
let basicAuth = {
method: "get",
url: "https://httpbin.org/basic-auth/user/passwd",
auth: {
username: "user",
password: "passwd"
}
}
axios(basicAuth).then(res => console.log(res.status))
superagent.get("https://httpbin.org/basic-auth/user/passwd")
.auth("user", "passwd")
.end((err, res) => console.log(res.statusCode))
All these libraries have a sufficient set of plugins created by the community (for example, the implementation of the promise api for the Request). However, from this point of view, it is worth highlighting SuperAgent, which has a specialized interface for connecting plugins (https://github.com/visionmedia/superagent#plugins)
For these tests, I used HTTPbin.
In the process of comparing their libraries, I came to the conclusion that they all have enough positive sides to use them.
Request – despite the fact that it is not cross-platform, it undoubtedly has the most opportunities out of the box. Ability to use NodeJS streams looks attractive.
Axios – as for me has the most understandable syntax and follows the idea of "principle of least surprise".
SuperAgent – also has a fairly understandable api, but much more important is the idea of its extensibility through plugins.
Node-Fetch – good old fetch api. A small number of dependencies and a familiar interface.