Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

request-promise

Package Overview
Dependencies
Maintainers
5
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

request-promise - npm Package Compare versions

Comparing version 0.4.3 to 1.0.0

4

lib/errors.js

@@ -10,3 +10,3 @@ 'use strict';

if (Error.captureStackTrace) {
if (Error.captureStackTrace) { // if required for non-V8 envs - see PR #40
Error.captureStackTrace(this);

@@ -26,3 +26,3 @@ }

if (Error.captureStackTrace) {
if (Error.captureStackTrace) { // if required for non-V8 envs - see PR #40
Error.captureStackTrace(this);

@@ -29,0 +29,0 @@ }

'use strict';
var Bluebird = require('./bluebird-fresh.js'),
CapturedTrace = require('./bluebird-captured-trace-fresh.js'),
var Bluebird = require('bluebird'),
assign = require('lodash/object/assign'),

@@ -12,3 +11,2 @@ forEach = require('lodash/collection/forEach'),

keys = require('lodash/object/keys'),
chalk = require('chalk'),
errors = require('./errors.js');

@@ -39,2 +37,8 @@

var defaultTransformations = {
HEAD: function (body, response, resolveWithFullResponse) {
return resolveWithFullResponse ? response : response.headers;
}
};
function RP$callback(err, response, body) {

@@ -75,3 +79,3 @@

try {
self._rp_resolve(self._rp_options.transform(body, response));
self._rp_resolve(self._rp_options.transform(body, response, self._rp_options.resolveWithFullResponse));
} catch (e) {

@@ -91,7 +95,2 @@ self._rp_reject(e);

// Mimic original behavior of errors emitted by request with no error listener registered
if (err && isFunction(self._rp_callbackOrig) === false && self._rp_promise_in_use !== true && self.listeners('error').length === 1) {
throw err;
}
}

@@ -112,3 +111,2 @@

});
self._rp_promise._rp_in_use = false;

@@ -122,2 +120,4 @@ self._rp_callbackOrig = self.callback;

options.transform = options.transform || defaultTransformations[options.method];
self._rp_options = options;

@@ -133,7 +133,2 @@ self._rp_options.simple = options.simple === false ? false : true;

function markPromiseInUse(requestInstance) {
requestInstance._rp_promise_in_use = true;
requestInstance._rp_promise._rp_in_use = true;
}
function expose(methodToExpose, exposeAs) {

@@ -145,8 +140,6 @@

if (!isUndefined(request.Request.prototype[exposeAs])) {
console.error(chalk.bold.bgRed('[Request-Promise] Unable to expose method "' + exposeAs + '". It is already implemented by Request. Please visit https://github.com/request/request-promise/wiki/Troubleshooting'));
return;
throw new Error('Unable to expose method "' + exposeAs + '". It is already implemented by Request. Please visit https://github.com/request/request-promise/wiki/Troubleshooting');
}
request.Request.prototype[exposeAs] = function RP$exposed() {
markPromiseInUse(this);
return this._rp_promise[methodToExpose].apply(this._rp_promise, arguments);

@@ -162,3 +155,2 @@ };

request.Request.prototype.promise = function RP$promise() {
markPromiseInUse(this);
return this._rp_promise;

@@ -168,14 +160,8 @@ };

var printRejectionReason = CapturedTrace.formatAndLogError || CapturedTrace.possiblyUnhandledRejection;
/* istanbul ignore next */ // Function covered but not seen by Instanbul.
request.bindCLS = function RP$bindCLS(ns) {
require('cls-bluebird')(ns);
};
Bluebird.onPossiblyUnhandledRejection(function (reason, promise) {
// For whatever reason we don't see _rp_in_use here at all after then is called. --> We compare to false instead of true.
if (promise._rp_in_use !== false) {
printRejectionReason(reason, 'Possibly unhandled ');
}
// else: The user did not call .then(...)
// --> We need to assume that this request is processed with a callback or a pipe etc.
});
module.exports = request;
{
"name": "request-promise",
"version": "0.4.3",
"version": "1.0.0",
"description": "The world-famous HTTP client 'Request' now Promises/A+ compliant. Powered by Bluebird.",

@@ -29,7 +29,7 @@ "keywords": [

"scripts": {
"test": "./node_modules/.bin/gulp validate"
"test": "./node_modules/.bin/gulp ci"
},
"dependencies": {
"bluebird": "^2.3",
"chalk": "^1.1.0",
"cls-bluebird": "^1.0.1",
"lodash": "^3.10.0",

@@ -42,4 +42,8 @@ "request": "^2.34"

"chai-as-promised": "4.3.x",
"chalk": "^1.1.1",
"cheerio": "^0.19.0",
"continuation-local-storage": "^3.1.4",
"event-stream": "3.3.x",
"gulp": "3.8.x",
"gulp-coveralls": "0.1.x",
"gulp-istanbul": "0.8.x",

@@ -46,0 +50,0 @@ "gulp-jshint": "1.10.x",

@@ -8,12 +8,4 @@ <a href="http://promisesaplus.com/">

---
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/request/request-promise?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [![Build Status](https://travis-ci.org/request/request-promise.svg?branch=master)](https://travis-ci.org/request/request-promise) [![Coverage Status](https://coveralls.io/repos/request/request-promise/badge.svg?branch=master&service=github)](https://coveralls.io/github/request/request-promise?branch=master) [![Dependency Status](https://david-dm.org/request/request-promise.svg)](https://david-dm.org/request/request-promise)
Using io.js? Please read the [support section](#support-for-iojs).
**Users of version 0.2.x please read the [migration instructions](#migrating-from-02x-to-03x)!**
---
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/request/request-promise?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [![Build Status](https://travis-ci.org/request/request-promise.svg?branch=master)](https://travis-ci.org/request/request-promise) [![Coverage Status](http://img.shields.io/badge/coverage-far%20beyond%20100%25-brightgreen.svg)](#can-i-trust-this-module) [![Dependency Status](https://david-dm.org/request/request-promise.svg)](https://david-dm.org/request/request-promise)
The world-famous HTTP client "Request" now Promises/A+ compliant. Powered by Bluebird.

@@ -23,14 +15,4 @@

## Request-Promise is a drop-in replacement for Request
Since version 0.3.0 Request-Promise is not a wrapper around Request anymore. It now adds a `.then(...)` method to the Request prototype and exports the original Request object. This means you can now use all features of Request.
Request-Promise is perfect for replacing callbacks with promises. However, if you want to pipe large quantities of data we recommend using Request for the reason [described below](#can-i-trust-this-module). Both Request and Request-Promise can be required side by side.
See the [migration instructions](#migrating-from-02x-to-03x) for important changes between 0.2.x and 0.3.x. Issues and pull requests for 0.2.x are still welcome.
## Installation
[![NPM](https://nodei.co/npm/request-promise.png?compact=true)](https://nodei.co/npm/request-promise/)
This module is installed via npm:

@@ -44,41 +26,115 @@

Node.js version 0.10 and up is supported.
## Cheat Sheet
## Examples
``` js
var rp = require('request-promise');
```
### Crawl a webpage
``` js
rp('http://www.google.com')
.then(console.dir)
.catch(console.error);
.then(function (htmlString) {
// Process html...
})
.catch(function (err) {
// Crawling failed...
});
```
// --> 'GET's and displays google.com
### Crawl a webpage better
``` js
var cheerio = require('cheerio'); // Basically jQuery for node.js
var options = {
uri : 'http://posttestserver.com/post.php',
method : 'POST'
uri: 'http://www.google.com',
transform: function (body) {
return cheerio.load(body);
}
};
rp(options)
.then(console.dir)
.catch(console.error);
.then(function ($) {
// Process html like you would with jQuery...
})
.catch(function (err) {
// Crawling failed or Cheerio choked...
});
```
// --> Displays response from server after post
### GET something from a JSON REST API
options.transform = function (data) { return data.length; };
``` js
var options = {
uri: 'https://api.github.com/user/repos',
qs: {
access_token: 'xxxxx xxxxx' // -> uri + '?access_token=xxxxx%20xxxxx'
},
headers: {
'User-Agent': 'Request-Promise'
},
json: true // Automatically parses the JSON string in the response
};
rp(options)
.then(console.dir)
.catch(console.error);
.then(function (repos) {
console.log('User has %d repos', repos.length);
})
.catch(function (err) {
// API call failed...
});
```
// transform is called just before promise is fulfilled
// --> Displays length of response from server after post
### POST data to a JSON REST API
``` js
var options = {
method: 'POST',
uri: 'http://posttestserver.com/post.php',
body: {
some: 'payload'
},
json: true // Automatically stringifies the body to JSON
};
// Get full response after DELETE
options = {
rp(options)
.then(function (parsedBody) {
// POST succeeded...
})
.catch(function (err) {
// POST failed...
});
```
### POST like HTML forms do
``` js
var options = {
method: 'POST',
uri: 'http://posttestserver.com/post.php',
form: {
some: 'payload' // Will be urlencoded
},
headers: {
/* 'content-type': 'application/x-www-form-urlencoded' */ // Set automatically
}
};
rp(options)
.then(function (body) {
// POST succeeded...
})
.catch(function (err) {
// POST failed...
});
```
### Get the full response instead of just the body
``` js
var options = {
method: 'DELETE',
uri: 'http://my-server/path/to/resource/1234',
resolveWithFullResponse: true
resolveWithFullResponse: true // <--- <--- <--- <---
};

@@ -90,5 +146,31 @@

})
.catch(console.error);
.catch(function (err) {
// Delete failed...
});
```
### Get a rejection only if the request failed for technical reasons
``` js
var options = {
uri: 'http://www.google.com/this-page-does-not-exist.html',
simple: false // <--- <--- <--- <---
};
rp(options)
.then(function (body) {
// Request succeeded but might as well be a 404
// Usually combined with resolveWithFullResponse = true to check response.statusCode
})
.catch(function (err) {
// Request failed due to technical reasons...
});
```
---
**For more options checkout the [Request docs](https://github.com/request/request#requestoptions-callback).**
---
## API in Detail

@@ -100,2 +182,3 @@

- With an [identical API](https://github.com/request/request): `require('request-promise') == require('request')` so to say
- However, the **USE OF STREAMS** (e.g. `.pipe(...)`) is **DISCOURAGED** because Request-Promise would grow the memory footprint for large requests unnecessarily high. Use the original Request library for that. You can use both libraries in the same project.
- Plus some methods on a request call object:

@@ -276,8 +359,9 @@ - `rp(...).then(...)` or e.g. `rp.post(...).then(...)` which turn `rp(...)` and `rp.post(...)` into promises

rp('http://google.com')
.catch(errors.StatusCodeError, function (reason) {
// The server responded with a status codes other than 2xx.
// Check reason.response.statusCode.
})
.catch(errors.RequestError, function (reason) {
// Handle a failed request for which Request provided an error...
// The request failed due to technical reasons.
// reason.cause is the Error object Request would pass into a callback.
})
.catch(errors.StatusCodeError, function (reason) {
// Handle responses with status codes other than 2xx...
});

@@ -294,3 +378,3 @@ ```

uri: 'http://google.com',
transform: function (body, response) {
transform: function (body, response, resolveWithFullResponse) {
return body.split('').reverse().join('');

@@ -302,3 +386,3 @@ }

.then(function (reversedBody) {
// #@-?
// ;D
});

@@ -310,3 +394,3 @@

function autoParse(body, response) {
function autoParse(body, response, resolveWithFullResponse) {
// FIXME: The content type string could contain additional values like the charset.

@@ -344,2 +428,35 @@ if (response.headers['content-type'] === 'application/json') {

The third `resolveWithFullResponse` parameter of the transform function is equivalent to the option passed with the request. This allows to distinguish whether just the transformed body or the whole response shall be returned by the transform function:
``` js
function reverseBody(body, response, resolveWithFullResponse) {
response.body = response.body.split('').reverse().join('');
return resolveWithFullResponse ? response : response.body;
}
```
## Experimental Support for Continuation Local Storage
Continuation Local Storage (CLS) is a great mechanism for backpacking data along asynchronous call chains that is best explained in [these slides](http://fredkschott.com/post/2014/02/conquering-asynchronous-context-with-cls/). If you want to use CLS you need to install the [continuation-local-storage package](https://www.npmjs.com/package/continuation-local-storage). Request-Promise internally uses the [cls-bluebird package](https://www.npmjs.com/package/cls-bluebird) to enable CLS also within the Bluebird promises.
Just call `rp.bindCLS(ns)` **ONCE** before your first request to activate CLS:
``` js
var rp = require('request-promise');
var cls = require('continuation-local-storage');
var ns = cls.createNamespace('testNS');
rp.bindCLS(ns);
ns.run(function () {
ns.set('value', 'hi');
rp('http://google.com')
.then(function () {
console.log(ns.get('value')); // -> hi
});
});
```
Since the [cls-bluebird package](https://www.npmjs.com/package/cls-bluebird) currently is just a quick and dirty implementation the CLS support is only experimental.
## Debugging

@@ -353,41 +470,43 @@

## Migrating from 0.2.x to 0.3.x
## Mocking Request-Promise
The module was rewritten with great care accompanied by plenty of automated tests. In most cases you can just update Request-Promise and your code will continue to work.
Usually you want to mock the whole request function which is returned by `require('request-promise')`. This is not possible by using a mocking library like [sinon.js](http://sinonjs.org) alone. What you need is a library that ties into the module loader and makes sure that your mock is returned whenever the tested code is calling `require('request-promise')`. [Mockery](https://github.com/mfncooper/mockery) is one of such libraries.
First and foremost Request-Promise now exposes Request directly. That means the API sticks to that of Request. The only methods and options introduced by Request-Promise are:
@florianschmidt1994 kindly shared his solution:
```javascript
before(function (done) {
- The `.then(...)` method
- The `.catch(...)` method
- The `.finally(...)` method
- The `.promise()` method
- The `simple` option
- The `resolveWithFullResponse` option
- The `transform` option
var filename = "fileForResponse";
mockery.enable({
warnOnReplace: false,
warnOnUnregistered: false,
useCleanCache: true
});
In regard to these methods and options Request-Promise 0.3.x is largely compatible with 0.2.x. All other parts of the API may differ in favor of the original behavior of Request.
mockery.registerMock('request-promise', function () {
var response = fs.readFileSync(__dirname + '/data/' + filename, 'utf8');
return Bluebird.resolve(response.trim());
});
### Changes and Removed Quirks
done();
});
(`rp_02x` and `rp_03x` refer to the function exported by the respective version of Request-Promise.)
after(function (done) {
mockery.disable();
mockery.deregisterAll();
done();
});
- `rp_02x(...)` returned a Bluebird promise. `rp_03x(...)` returns a Request instance with a `.then(...)`, a `.catch(...)`, and a `.finally(...)` method. If you used any Bluebird method other than `.then(...)`, `.catch(...)`, and `.finally(...)` as the **FIRST** method in the promise chain, your code needs a small change to use Request-Promise 0.3.2 and up: Use the [`.promise()` method](#promise---for-advanced-use-cases) to retrieve the full-fledged Bluebird promise. E.g. `rp_02x(...).bind(...)` needs to be changed to `rp_03x(...).promise().bind(...)`
Please note that this only applies to the **FIRST method in the chain**. E.g. `rp_03x(...).then(...).spread(...)` is still possible. Only something like `rp_02x(...).spread(...)` needs to be changed to `rp_03x(...).promise().spread(...)`.
If, however, you have a large code base in production and making this small change is not an option or you think that exposing another Bluebird method directly on the Request instance would be more convenient for a common use case, please open an issue.
- The options `simple` and `resolveWithFullResponse` must be of type boolean. If they are of different type Request-Promise 0.3.x will use the defaults. In 0.2.x the behavior for non-boolean values was different.
- The object passed as the reason of a rejected promise contains an `options` object that differs between both versions. Especially the `method` property is not set if the default (GET) is applied.
- If you called `rp_02x(...)` without appending a `.then(...)` call occurring errors may have been discarded. Request-Promise 0.3.x may now throw those. However, if you append a `.then(...)` call those errors reject the promise in both versions.
- `rp_03x.head(...)` throws an exception if the options contain a request body. This is due to Requests original implementation which was not used in Request-Promise 0.2.x.
- `rp_02x.request` does not exist in Request-Promise 0.3.x since Request is exported directly. (`rp_02x.request === rp_03x`)
describe('custom test case', function () {
// Test some function/module/... which uses request-promise
// and it will always receive the predefined "fileForResponse" as data, e.g.:
var rp = require('request-promise');
rp(...).then(function(data) {
// ➞ data is what is in fileForResponse
});
});
```
## Support for io.js
Based on that you may now build a more sophisticated mock. [Sinon.js](http://sinonjs.org) may be of help as well.
We added io.js to our Travis CI build and all tests are green. However, they mostly cover the functionality of Request-Promise itself. Barely of Request and Bluebird. At the time of writing Request did but Bluebird didn't add io.js to its build, yet. So please use io.js with care.
## Can I trust this module?
The approx. 120 lines of code – on top of the well tested libraries Request and Bluebird – are covered by over 60 tests producing a test coverage of 100% and beyond. Additionally, the original tests of Request were executed on Request-Promise to ensure that we can call it "a drop-in replacement for Request". So yes, we did our best to make Request-Promise live up to the quality Request and Bluebird are known for.
However, there is one important design detail: Request-Promise passes a callback to each Request call which it uses to resolve or reject the promise. The callback is also registered if you don't use the promise features in a certain request. E.g. you may only use streaming: `rp(...).pipe(...)` As a result, [additional code](https://github.com/request/request/blob/master/request.js#L1010-L1059) is executed that buffers the streamed data and passes it as the response body to the "complete" event. If you stream [large quantities of data](https://github.com/request/request-promise/issues/53) the buffer grows big and that has an impact on your memory footprint. In these cases you can just `var request = require('request');` and use `request` for streaming large quantities of data.
## Contributing

@@ -409,4 +528,13 @@

### Main Branch
- v1.0.0 (2015-10-11)
- **Braking Change**: Some errors that were previously thrown synchronously - e.g. for wrong input parameters - are now passed to the rejected promise instead
*(Thanks to @josnidhin for suggesting that in [issue #43](https://github.com/request/request-promise/issues/43))*
- For HEAD requests the headers instead of an empty body is returned (unless `resolveWithFullResponse = true` is used)
*(Thanks to @zcei for proposing the change in [issue #58](https://github.com/request/request-promise/issues/58))*
- Extended `transform` function by a third `resolveWithFullResponse` parameter
- Added experimental support for continuation local storage
*(Thanks to @silverbp preparing this in [issue #64](https://github.com/request/request-promise/issues/64))*
- Added node.js 4 to the Travis CI build
- Updated the README
*(Thanks to many people for their feedback in issues [#55](https://github.com/request/request-promise/issues/55) and [#59](https://github.com/request/request-promise/issues/59))*
- v0.4.3 (2015-07-27)

@@ -425,3 +553,3 @@ - Reduced overhead by just requiring used lodash functions instead of the whole lodash library

- **Minor Braking Change:** The reject reason objects became actual Error objects. However, `typeof reason === 'object'` still holds true and the error objects have the same properties as the previous reason objects. If the reject handler only accesses the properties on the reason object - which is usually the case - no migration is required.
- [Added io.js](#support-for-iojs) and node.js 0.12 to the Travis CI build
- Added io.js and node.js 0.12 to the Travis CI build
- v0.3.3 (2015-01-19)

@@ -437,20 +565,6 @@ - Fixed handling possibly unhandled rejections to work with the latest version of Bluebird

- v0.3.0 (2014-11-10)
- Carefully rewritten from scratch to make Request-Promise a [drop-in replacement for Request](#request-promise-is-a-drop-in-replacement-for-request)
- Carefully rewritten from scratch to make Request-Promise a drop-in replacement for Request
### Version 0.2.x Branch
- v0.2.7 (2014-11-17)
- Fixed http method shortcuts like `rp.get(...)` when used with passing an options object
*(Thanks to @hjpbarcelos for reporting this in [issue #29](https://github.com/request/request-promise/issues/29))*
- v0.2.6 (2014-11-09)
- When calling `rp.defaults(...)` the passed `resolveWithFullResponse` option is not always overwritten by the default anymore.
- The function passed as the `transform` option now also gets the full response as the second parameter. The new signature is: `function (body, response) { }`
*(Thanks to @khankuan for his feedback in [issue #24](https://github.com/request/request-promise/issues/24))*
- If the transform function throws an exception it is caught and the promise is rejected with it.
- v0.2.5 (2014-11-06)
- The Request instance which is wrapped by Request-Promise is exposed as `rp.request`.
*(Thanks to @hjpbarcelos for his feedback in [issue #23](https://github.com/request/request-promise/issues/23))*
## MIT Licensed
See the [LICENSE file](LICENSE) for details.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc