Using bluebird and create-error to make request easier to use. The most notible difference between this library and simply "promisifying" the request module is that this library will automatically reject the promise with an HTTPError
if the response idicates an HTTP error (e.g. response.statusCode >= 400
). HTTP as Promised supports all the same options you'd pass to request as well as all of request's convenience methods.
HTTP as Promised is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.
var $http = require('http-as-promised');
$http('https://www.github.com')
.spread(function (response, body){
console.log(body) // HTTP request was successful
})
.catch(function (error){
console.error(error) // HTTP request was unsuccessful
});
In addition to all of the options that the request module accepts, there are two options specific to HTTP as Promised:
-
error
- If set tofalse
HTTP as Promised will no longer reject the response with anHTTPError
based on the its HTTP status code. Defaults totrue
. See below. -
resolve
- Indicates the fulfillment value with which you want the HTTP promise to be resolved. Accepts a string or array of strings. Possible values:-
['response', 'body']
(default) - By default HTTP as Promised will resolve promises with an array containing theresponse
(http.IncomingMessage
object) followed by the responsebody
(String
,Buffer
, or JSON object if thejson
option is supplied). This means that for simple access to thebody
you would probably want to use.spread()
instead of.then()
as seen in the example above. -
['body', 'response']
- This swaps the ordering of the resolved array so that the "body" comes before the "response" object in the resolved array. -
'response'
- This will resolve the promise with just theresponse
object -
'body'
- This is probably the one that is going to be the most useful setting for developers looking for a simple interface. Using this means you can easily pass the promises around and know that the fulfillment value is just going to be thebody
object.var url = 'https://www.npm.org', nock = require('nock')(url); nock.post('/').reply(200, 'Hello World!'); $http.post(url, { resolve: 'body' }).then(console.log);
"Hello World"
-
HTTP as Promised exposes a custom HTTPError
constructor which is extended from the global Error
constructor. The HTTPError
constructor also exposes more specific types of HTTPError
constructors both for ranges/types of HTTP Errors (4xx/client and 5xx/server) as well as status-code-specific HTTP errors (404, 418, 509, etc.). When instanciated, each of these constructors will be a fully-fledged instanceof Error
with stack traces and everything. In addition to the message
and name
properties, instances of HTTPError
will also include additional HTTP specific information:
var $http = require('http-as-promised'),
err = new $http.error[505];
console.log('Error: ', err instanceof Error);
console.log('HTTP Error: ', err instanceof $http.error);
console.log('HTTP 5xx Error: ', err instanceof $http.error['5xx']);
console.log('HTTP Server Error:', err instanceof $http.error['server']);
throw err;
Error: true
HTTP Error: true
HTTP 5xx Error: true
HTTP Server Error: true
HTTPError: 505 HTTP Version Not Supported
at Object.<anonymous> (/test.js:2:7)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:906:3
{ [HTTPError: 505 HTTP Version Not Supported]
statusCode: 505,
title: 'HTTP Version Not Supported',
summary: 'server does not support the HTTP protocol version',
range: '5xx',
type: 'ServerError',
message: '505 HTTP Version Not Supported' }
When an HTTPError
is the reason why a response was rejected by HTTP as Promised, it will include some additional properties:
var $http = require('http-as-promised'),
url = 'https://www.npm.org',
nock = require('nock')(url);
nock.get('/bogus/url').reply(404, 'Cannot find /bogus/url');
$http(url+'/bogus/url').catch(console.log);
{ [HTTPError: 404 Not Found]
statusCode: 404,
title: 'Not Found',
summary: 'requested resource could not be found',
range: '4xx',
type: 'ClientError',
message: '404 Not Found',
body: 'Cannot find /bogus/url',
response: [Object: IncomingMessage]
options:
{ error: true,
method: 'GET',
uri: 'https://www.npm.org/bogus/url' } }
Since we're using Bluebird to construct our promises, handling specific HTTP Errors is a breeze using .catch()
:
var $http = require('http-as-promised'),
url = 'https://stackoverflow.com',
nock = require('nock')(url);
nock.get('/teapot').reply(418);
$http(url+'/teapot')
.catch($http.error[418], function (e){
// Catch 418 I'm A Teapot HTTP Errors
})
.catch($http.error.client, function (e){
// Catch any remaining Client HTTP Errors
})
.catch($http.error['4xx'], function (e){
// An alias for $http.error.client
})
.catch($http.error, function (e){
// Catch any other HTTP Errors that weren't already caught
})
.catch(function (e){
// Catch any other type of Error
})
For better stack traces you can enable bluebird's longStackTraces
, as well as bluebird's other error management configuration methods by calling them on HTTP as Promised:
$http.longStackTraces();
nock.get('/').reply(420);
denialOfService(url).catch(err);
function denialOfService(url){
return $http(url);
}
HTTPError: 420 Enhance Your Calm
at Request.HTTP_RESPONSE [as _callback] (http.promise.js:73:25)
at Request.self.callback (node_modules/request/request.js:237:22)
at Request.EventEmitter.emit (events.js:98:17)
at Request.<anonymous> (node_modules/request/request.js:1146:14)
at Request.EventEmitter.emit (events.js:117:20)
at OutgoingMessage.<anonymous> (node_modules/request/request.js:1097:12)
at OutgoingMessage.EventEmitter.emit (events.js:117:20)
at node_modules/nock/lib/request_overrider.js:419:18
at Object._onImmediate (node_modules/nock/lib/request_overrider.js:438:9)
From previous event:
at new Promise (node_modules/bluebird/js/main/promise.js:82:37)
at HTTP (http.promise.js:56:12)
at denialOfService (test.js:12:10)
at Object.<anonymous> (test.js:9:1)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
{ [HTTPError: 420 Enhance Your Calm]
statusCode: 420,
title: 'Enhance Your Calm',
summary: 'Twitter rate limiting',
range: '4xx',
type: 'ClientError',
message: '420 Enhance Your Calm',
body: '',
options: { error: true, method: 'GET', uri: 'https://twitter.com' } }
You can directly access the request module used by the HTTP as Promised module:
var $http = require('http-as-promised');
$http.request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))