An extremely lightweight HTTP request client. Supports: http, https, redirects, cookies, content-encoding, multipart/form-data. Returns: Promise.
The module includes 1 function:
request
It also exports 2 additional functions that are included as dependencies:
denodeify
denodeify_net_request
npm install --save @warren-bank/node-request
request(options[, POST_data, config])
options
{string} | {Object} | {Array<{string} | {Object}>}- {string} value
- expected to contain a URL
- {Object} value
- for a complete list of all attributes,
please refer to the Node.js api documentation for:
- for a complete list of all attributes,
- {Array<>} value
- {string} URL values are parsed to {Object} values
- combines its elements into a single {Object} value
- {string} value
POST_data
{string} | {Object} | {Buffer} | {stream.Readable} | {Array<Object>}- {string} value
- when Content-Type header is undefined
- Content-Type header is given the value: 'application/x-www-form-urlencoded'
- when Content-Type header is undefined
- {Object} value
- is serialized to a {string} value based on the value of Content-Type header
- 'application/json':
- converted to JSON
- otherwise:
- converted to querystring format
- ex:
"a=1&b=2"
- 'application/json':
- when Content-Type header is undefined
- Content-Type header is given the value: 'application/x-www-form-urlencoded'
- is serialized to a {string} value based on the value of Content-Type header
- {Buffer} | {stream.Readable} values
- when Content-Type header is undefined
- Content-Type header is given the value: 'application/octet-stream'
- when Content-Type header is undefined
- {Array<Object>} value
- Content-Type header is given the value: 'multipart/form-data'
- {Object} value required attributes:
name
- type: {string}
value
- type: {string} | {number} | {Buffer} | {Object}
- {string} | {number} | {Buffer} values
- sent verbatim
- {Object} value attributes:
file
- type: {stream.Readable}
filename
- type: {string}
- when
file
is undefined:- required
- value is an absolute filepath to a file that exists and is readable
- when
file
is defined:- optional
- value only needs a filename
mime
ormime-type
orcontent-type
orheaders.content-type
- type: {string}
- prioritized as given, in descending order
- highest priority value sets the Content-Type header for the file
- when no value is defined:
- if
filename
is defined:- file extension in
filename
is used to infer the Content-Type header for the file
- file extension in
- otherwise:
- Content-Type header for the file is given the value: 'application/octet-stream'
- if
- {string} value
config
{Object}normalizePath
{Boolean} (defaults totrue
)followRedirect
{Boolean} (defaults totrue
)maxRedirects
{number} (defaults to10
)binary
{Boolean} (defaults tofalse
)false
:- data is returned in {String} (utf8 encoding)
true
:- data is returned in {Buffer}
stream
{Boolean} (defaults tofalse
)false
:response
attribute of resolved Promise is a value that contains the entire data file (stored in memory)- data type of
response
is either {Buffer} or {String}, as determined bybinary
option
true
:response
attribute of resolved Promise is a Readable stream
validate_status_code
{Function} | {false}- This
config
option is part of the API fromdenodeify_net_request
. - It creates a Proxy that traps calls to
http.request
andhttps.request
.
The Proxy accepts this value (to change its default behavior)
to determine what to do when a HTTP status code indicates something other than "200 OK". - The default value causes an Error object to propogate up the Promise chain.
This Error object includes some useful information.
In fact, the information produced by the default handler
is what enablesrequest
to follow redirects.
As such, please be careful if you choose to override this function.
- This
cookieJar
{CookieJar} | {string} | {true}CookieJar
:- instance of require('tough-cookie').CookieJar
- choose your own cookie store
- instance of require('tough-cookie').CookieJar
string
:- file path to the persistent text file used to store cookie data
- file is created when it does not already exist
- constructs an instance of
CookieJar
using the cookie store:
"tough-cookie-filestore2"- this cookie store uses JSON format
true
:- constructs an instance of
CookieJar
using the cookie store:
require('tough-cookie/lib/memstore').MemoryCookieStore- this cookie store is initialized empty and the cookies it collects are not persisted
- this is only useful when:
- the request is redirected at least once
- cookies are added earlier in the chain of redirects than they are ultimately consumed
- constructs an instance of
- default:
- no cookie jar is used
- Returns: {Promise}
- value is resolved to an {Object}:
{url, redirects, response}
url
is a {string} that represents the original requestoptions
redirects
is an {Array} of {string}- each value is a url in the chain of redirects
- the ordering is chronological;
the first element was the first redirect (fromurl
)
response
is the data payloadconfig.binary
determines the data's encoding (ie: {Buffer} or utf8 {String})config.stream
determines whether the value is a Readable stream or a memory buffer,
either of which is formatted in the chosen encoding- the
response
Object always includes the following attributes:statusCode
{integer}headers
{Object}
- value is resolved to an {Object}:
const {request, denodeify} = require('@warren-bank/node-request')
const fs = {
writeFile: denodeify( require('fs').writeFile ),
createWriteStream: require('fs').createWriteStream
}
const sep = Array(35).join('-')
const log = function(msg, {div=' ', pre='', post=''}={}){
if (Array.isArray(msg)) msg = msg.join(div)
msg = pre + (msg ? msg : '') + post
process.stdout.write(msg)
}
/**
* helper:
* - format a message with information about a successful network request
* - include the downloaded text data
**/
const process_text_success = function({url, redirects, response}){
log((
`${sep}${sep}
URL of initial request:
${url}
Chain of URL redirects:
${(redirects && redirects.length) ? redirects.join("\n ") : '[]'}
Data response for URL of final request:
${sep}
${response}`
), {post:"\n"})
}
/**
* helper:
* - format a message with information about a successful network request
* - save the binary data Buffer to disk
**/
const process_binary_success = function({url, redirects, response}, filename){
log((
`${sep}${sep}
URL of initial request:
${url}
Chain of URL redirects:
${(redirects && redirects.length) ? redirects.join("\n ") : '[]'}`
), {post:"\n\n"})
fs.writeFile(filename, response, 'binary')
.then(() => {
log(['Binary data Buffer saved to file:', filename], {div:"\n ", post:"\n\n"})
})
.catch((error) => {
log(['Error: Failed to save binary data Buffer to file:', filename], {div:"\n ", post:"\n\n"})
log(['Error message:', error.message], {div:"\n ", post:"\n\n"})
})
}
/**
* helper:
* - format a message with information about a successful network request
* - save the binary data stream to disk
**/
const process_binary_stream_success = function({url, redirects, response}, filename){
log((
`${sep}${sep}
URL of initial request:
${url}
Chain of URL redirects:
${(redirects && redirects.length) ? redirects.join("\n ") : '[]'}`
), {post:"\n\n"})
response
.pipe( fs.createWriteStream(filename) )
.on('finish', () => {
log(['Binary data Stream saved to file:', filename], {div:"\n ", post:"\n\n"})
})
.on('error', (error) => {
log(['Error: Failed to save binary data Stream to file:', filename], {div:"\n ", post:"\n\n"})
log(['Error message:', error.message], {div:"\n ", post:"\n\n"})
response.destroy()
})
}
/**
* helper:
* - format an error message
**/
const process_error = function(error){
log((
`${sep}${sep}
Error:
${error.message}
HTTP status code:
${error.statusCode ? error.statusCode : 'unavailable'}
URL of initial request:
${error.url ? error.url : 'unavailable'}
Chain of URL redirects:
${(error.redirects && error.redirects.length) ? error.redirects.join("\n ") : '[]'}
Unfollowed redirect:
${error.location ? error.location : 'none'}`
), {post:"\n\n"})
}
// example: perform a request that succeeds after performing 2 redirects and changing protocol from 'http' to 'https'
request('http://github.com/warren-bank/node-denodeify/raw/master/package.json')
.then(process_text_success)
.catch(process_error)
// example: perform the same request but configure the maximum number of permitted redirects to result in an Error
request('http://github.com/warren-bank/node-denodeify/raw/master/package.json', '', {maxRedirects: 1})
.then(process_text_success)
.catch(process_error)
// example: perform a request that succeeds after performing 1 redirect and retrieves binary data in a Buffer
request('https://github.com/warren-bank/node-denodeify/archive/master.zip', '', {binary: true})
.then((data) => {process_binary_success(data, 'denodeify.Buffer.zip')})
.catch(process_error)
// example: perform the same request but retrieve the binary data from a Readable stream
request('https://github.com/warren-bank/node-denodeify/archive/master.zip', '', {binary: true, stream: true})
.then((data) => {process_binary_stream_success(data, 'denodeify.Stream.zip')})
.catch(process_error)
These HTTP method convenience functions act just like request()
but with a default method:
- request.get(): Defaults to
method: "GET"
. - request.post(): Defaults to
method: "POST"
. - request.put(): Defaults to
method: "PUT"
. - request.patch(): Defaults to
method: "PATCH"
. - request.delete() / request.del(): Defaults to
method: "DELETE"
. - request.head(): Defaults to
method: "HEAD"
. - request.options(): Defaults to
method: "OPTIONS"
.
- Node.js version: v8.6.0 (and higher)
- transitive dependency requirements:
- v8.06.00+:
@warren-bank/node-denodeify
- v8.06.00+:
- transitive dependency requirements:
- copyright: Warren Bank
- license: GPL-2.0