Code Monkey home page Code Monkey logo

request-promise's Introduction

Promises/A+ logo

Request-Promise

Gitter Build Status Coverage Status Dependency Status Known Vulnerabilities

Deprecated!

As of Feb 11th 2020, request is fully deprecated. No new changes are expected to land. In fact, none have landed for some time. This package is also deprecated because it depends on request.

Fyi, here is the reasoning of request's deprecation and a list of alternative libraries.


The simplified HTTP request client 'request' with Promise support. Powered by Bluebird.

Request and Bluebird are pretty awesome, but I found myself using the same design pattern. Request-Promise adds a Bluebird-powered .then(...) method to Request call objects. By default, http response codes other than 2xx will cause the promise to be rejected. This can be overwritten by setting options.simple = false.

Also check out the new libraries that are very similar to request-promise v4:


Migration from v3 to v4

  1. request became a peer dependency. Thus make sure that request is installed into your project as a direct dependency. (npm install --save request)
  2. Continuation Local Storage is no longer supported. However, you can get back the support by using request-promise-any.
  3. When you migrated your transform function to v3 and had to add if (!(/^2/.test('' + response.statusCode))) { return resolveWithFullResponse ? response : body; } you may now set the option transform2xxOnly = true instead.

Migration from v2 to v3

  1. The handling of the transform function got overhauled. This has two effects:

    • StatusCodeError.response is the transformed instead of the original response now. This error is thrown for non-2xx responses when options.simple is true (default). Please update your transform functions to also cover the transformation of non-2xx responses. To get the old behavior you may add if (!(/^2/.test('' + response.statusCode))) { return resolveWithFullResponse ? response : body; } to the first line of your transform functions that are used for requests with options.simple === true. However, you may prefer updating your transform functions to being able to transform 2xx as well as non-2xx responses because this decouples their implementation from the use of the simple option when doing requests.
    • If a transform operation throws an error, the request will be rejected with a TransformError. Its cause attribute contains the error thrown by the transform operation. Previously, the request was rejected directly with the error thrown by the transform operation. Wrapping it into a TransformError makes the error handling easier.
  2. Bluebird got updated from v2 to v3. This won't make a difference for most use cases. However, if you use advanced Promise chains starting with the Promise returned by Request-Promise, please check Bluebird's new features and changes.


Installation

This module is installed via npm:

npm install --save request
npm install --save request-promise

request is defined as a peer-dependency and thus has to be installed separately.

Cheat Sheet

var rp = require('request-promise');

Since request-promise wraps around request everything that works with request also works with request-promise. Also check out the request docs for more examples.

Crawl a webpage

rp('http://www.google.com')
    .then(function (htmlString) {
        // Process html...
    })
    .catch(function (err) {
        // Crawling failed...
    });

Crawl a webpage better

var cheerio = require('cheerio'); // Basically jQuery for node.js

var options = {
    uri: 'http://www.google.com',
    transform: function (body) {
        return cheerio.load(body);
    }
};

rp(options)
    .then(function ($) {
        // Process html like you would with jQuery...
    })
    .catch(function (err) {
        // Crawling failed or Cheerio choked...
    });

GET something from a JSON REST API

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(function (repos) {
        console.log('User has %d repos', repos.length);
    })
    .catch(function (err) {
        // API call failed...
    });

POST data to a JSON REST API

Set option.body to your data and json: true to encode the body as JSON. See below for HTML forms.

var options = {
    method: 'POST',
    uri: 'http://api.posttestserver.com/post',
    body: {
        some: 'payload'
    },
    json: true // Automatically stringifies the body to JSON
};

rp(options)
    .then(function (parsedBody) {
        // POST succeeded...
    })
    .catch(function (err) {
        // POST failed...
    });

POST like HTML forms do

Pass your data to options.form to encode the body the same way as HTML forms do:

var options = {
    method: 'POST',
    uri: 'http://posttestserver.com/post.php',
    form: {
        // Like <input type="text" name="name">
        name: 'Josh'
    },
    headers: {
        /* 'content-type': 'application/x-www-form-urlencoded' */ // Is set automatically
    }
};

rp(options)
    .then(function (body) {
        // POST succeeded...
    })
    .catch(function (err) {
        // POST failed...
    });

If you want to include a file upload then use options.formData:

var options = {
    method: 'POST',
    uri: 'http://posttestserver.com/post.php',
    formData: {
        // Like <input type="text" name="name">
        name: 'Jenn',
        // Like <input type="file" name="file">
        file: {
            value: fs.createReadStream('test/test.jpg'),
            options: {
                filename: 'test.jpg',
                contentType: 'image/jpg'
            }
        }
    },
    headers: {
        /* 'content-type': 'multipart/form-data' */ // Is set automatically
    }
};

rp(options)
    .then(function (body) {
        // POST succeeded...
    })
    .catch(function (err) {
        // POST failed...
    });

Include a cookie

var tough = require('tough-cookie');

// Easy creation of the cookie - see tough-cookie docs for details
let cookie = new tough.Cookie({
    key: "some_key",
    value: "some_value",
    domain: 'api.mydomain.com',
    httpOnly: true,
    maxAge: 31536000
});

// Put cookie in an jar which can be used across multiple requests
var cookiejar = rp.jar();
cookiejar.setCookie(cookie, 'https://api.mydomain.com');
// ...all requests to https://api.mydomain.com will include the cookie

var options = {
    uri: 'https://api.mydomain.com/...',
    jar: cookiejar // Tells rp to include cookies in jar that match uri
};

rp(options)
    .then(function (body) {
        // Request succeeded...
    })
    .catch(function (err) {
        // Request failed...
    });

Get the full response instead of just the body

var options = {
    method: 'DELETE',
    uri: 'http://my-server/path/to/resource/1234',
    resolveWithFullResponse: true    //  <---  <---  <---  <---
};

rp(options)
    .then(function (response) {
        console.log("DELETE succeeded with status %d", response.statusCode);
    })
    .catch(function (err) {
        // Delete failed...
    });

Get a rejection only if the request failed for technical reasons

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.


API in Detail

Consider Request-Promise being:

  • A Request object
    • With an identical API: require('request-promise') == require('request') so to say
    • However, STREAMING THE RESPONSE (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:
    • rp(...).then(...) or e.g. rp.post(...).then(...) which turn rp(...) and rp.post(...) into promises
    • rp(...).catch(...) or e.g. rp.del(...).catch(...) which is the same method as provided by Bluebird promises
      • Errors that the request library would pass to the callback are wrapped by request-promise and then passed to the catch handler. See code example below.
    • rp(...).finally(...) or e.g. rp.put(...).finally(...) which is the same method as provided by Bluebird promises
    • rp(...).cancel() or e.g. rp.get(...).cancel() which cancels the request
    • rp(...).promise() or e.g. rp.head(...).promise() which returns the underlying promise so you can access the full Bluebird API
  • Plus some additional options:
    • simple = true which is a boolean to set whether status codes other than 2xx should also reject the promise
    • resolveWithFullResponse = false which is a boolean to set whether the promise should be resolved with the full response or just the response body
    • transform which takes a function to transform the response into a custom value with which the promise is resolved
    • transform2xxOnly = false which is a boolean to set whether the transform function is applied to all responses or only to those with a 2xx status code

The objects returned by request calls like rp(...) or e.g. rp.post(...) are regular Promises/A+ compliant promises and can be assimilated by any compatible promise library.

The methods .then(...), .catch(...), and .finally(...) - which you can call on the request call objects - return a full-fledged Bluebird promise. That means you have the full Bluebird API available for further chaining. E.g.: rp(...).then(...).spread(...) If, however, you need a method other than .then(...), .catch(...), or .finally(...) to be FIRST in the chain, use .promise(): rp(...).promise().bind(...).then(...)

.then(onFulfilled, onRejected)

// As a Request user you would write:
var request = require('request');

request('http://google.com', function (err, response, body) {
    if (err) {
        handleError({ error: err, response: response, ... });
    } else if (!(/^2/.test('' + response.statusCode))) { // Status Codes other than 2xx
        handleError({ error: body, response: response, ... });
    } else {
        process(body);
    }
});

// As a Request-Promise user you can now write the equivalent code:
var rp = require('request-promise');

rp('http://google.com')
    .then(process, handleError);
// The same is available for all http method shortcuts:
request.post('http://example.com/api', function (err, response, body) { ... });
rp.post('http://example.com/api').then(...);

.catch(onRejected)

rp('http://google.com')
    .catch(handleError);

// ... is syntactical sugar for:

rp('http://google.com')
    .then(null, handleError);


// However, this:
rp('http://google.com')
    .then(process)
    .catch(handleError);

// ... is safer than:
rp('http://google.com')
    .then(process, handleError);

For more info on .then(process).catch(handleError) versus .then(process, handleError), see Bluebird docs on promise anti-patterns.

.finally(onFinished)

rp('http://google.com')
    .finally(function () {
	    // This is called after the request finishes either successful or not successful.
	});

.cancel()

This method cancels the request using Bluebird's cancellation feature.

When .cancel() is called:

  • the promise will neither be resolved nor rejected and
  • the request is aborted.

.promise() - For advanced use cases

In order to not pollute the Request call objects with the methods of the underlying Bluebird promise, only .then(...), .catch(...), and .finally(...) were exposed to cover most use cases. The effect is that any methods of a Bluebird promise other than .then(...), .catch(...), or .finally(...) cannot be used as the FIRST method in the promise chain:

// This works:
rp('http://google.com').then(function () { ... });
rp('http://google.com').catch(function () { ... });

// This works as well since additional methods are only used AFTER the FIRST call in the chain:
rp('http://google.com').then(function () { ... }).spread(function () { ... });
rp('http://google.com').catch(function () { ... }).error(function () { ... });

// Using additional methods as the FIRST call in the chain does not work:
// rp('http://google.com').bind(this).then(function () { ... });

// Use .promise() in these cases:
rp('http://google.com').promise().bind(this).then(function () { ... });

Fulfilled promises and the resolveWithFullResponse option

// Per default the body is passed to the fulfillment handler:
rp('http://google.com')
    .then(function (body) {
        // Process the html of the Google web page...
    });

// The resolveWithFullResponse options allows to pass the full response:
rp({ uri: 'http://google.com', resolveWithFullResponse: true })
    .then(function (response) {
        // Access response.statusCode, response.body etc.
    });

Rejected promises and the simple option

// The rejection handler is called with a reason object...
rp('http://google.com')
    .catch(function (reason) {
        // Handle failed request...
	});

// ... and would be equivalent to this Request-only implementation:
var options = { uri: 'http://google.com' };

request(options, function (err, response, body) {
    var reason;
    if (err) {
        reason = {
            cause: err,
            error: err,
            options: options,
            response: response
        };
	} else if (!(/^2/.test('' + response.statusCode))) { // Status Codes other than 2xx
        reason = {
            statusCode: response.statusCode,
            error: body,
            options: options,
            response: response
        };
    }

    if (reason) {
        // Handle failed request...
    }
});


// If you pass the simple option as false...
rp({ uri: 'http://google.com', simple: false })
    .catch(function (reason) {
        // Handle failed request...
	});

// ... the equivalent Request-only code would be:
request(options, function (err, response, body) {
    if (err) {
        var reason = {
            cause: err,
            error: err,
            options: options,
            response: response
        };
        // Handle failed request...
	}
});
// E.g. a 404 would now fulfill the promise.
// Combine it with resolveWithFullResponse = true to check the status code in the fulfillment handler.

With version 0.4 the reason objects became Error objects with identical properties to ensure backwards compatibility. These new Error types allow targeted catch blocks:

var errors = require('request-promise/errors');

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

The transform function

You can pass a function to options.transform to generate a custom fulfillment value when the promise gets resolved.

// Just for fun you could reverse the response body:
var options = {
	uri: 'http://google.com',
    transform: function (body, response, resolveWithFullResponse) {
        return body.split('').reverse().join('');
    }
};

rp(options)
    .then(function (reversedBody) {
        // ;D
    });


// However, you could also do something useful:
var $ = require('cheerio'); // Basically jQuery for node.js

function autoParse(body, response, resolveWithFullResponse) {
    // FIXME: The content type string could contain additional values like the charset.
    // Consider using the `content-type` library for a robust comparison.
    if (response.headers['content-type'] === 'application/json') {
        return JSON.parse(body);
    } else if (response.headers['content-type'] === 'text/html') {
        return $.load(body);
    } else {
        return body;
    }
}

options.transform = autoParse;

rp(options)
    .then(function (autoParsedBody) {
        // :)
    });


// You can go one step further and set the transform as the default:
var rpap = rp.defaults({ transform: autoParse });

rpap('http://google.com')
    .then(function (autoParsedBody) {
        // :)
    });

rpap('http://echojs.com')
    .then(function (autoParsedBody) {
        // =)
    });

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:

function reverseBody(body, response, resolveWithFullResponse) {
    response.body = response.body.split('').reverse().join('');
    return resolveWithFullResponse ? response : response.body;
}

As of Request-Promise v3 the transform function is ALWAYS executed for non-2xx responses. When options.simple is set to true (default) then non-2xx responses are rejected with a StatusCodeError. In this case the error contains the transformed response:

var options = {
	uri: 'http://the-server.com/will-return/404',
	simple: true,
    transform: function (body, response, resolveWithFullResponse) { /* ... */ }
};

rp(options)
    .catch(errors.StatusCodeError, function (reason) {
        // reason.response is the transformed response
    });

You may set options.transform2xxOnly = true to only execute the transform function for responses with a 2xx status code. For other status codes โ€“ independent of any other settings, e.g. options.simple โ€“ the transform function is not executed.

Error handling

If the transform operation fails (throws an error) the request will be rejected with a TransformError:

var errors = require('request-promise/errors');

var options = {
	uri: 'http://google.com',
    transform: function (body, response, resolveWithFullResponse) {
        throw new Error('Transform failed!');
    }
};

rp(options)
    .catch(errors.TransformError, function (reason) {
        console.log(reason.cause.message); // => Transform failed!
        // reason.response is the original response for which the transform operation failed
    });

Experimental Support for Continuation Local Storage

Continuation Local Storage is no longer supported. However, you can get back the support by using request-promise-any.

Debugging

The ways to debug the operation of Request-Promise are the same as described for Request. These are:

  1. Launch the node process like NODE_DEBUG=request node script.js (lib,request,otherlib works too).
  2. Set require('request-promise').debug = true at any time (this does the same thing as #1).
  3. Use the request-debug module to view request and response headers and bodies. Instrument Request-Promise with require('request-debug')(rp);.

Mocking Request-Promise

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 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 is one of such libraries.

@florianschmidt1994 kindly shared his solution:

before(function (done) {

    var filename = "fileForResponse";
    mockery.enable({
        warnOnReplace: false,
        warnOnUnregistered: false,
        useCleanCache: true
    });

    mockery.registerMock('request-promise', function () {
        var response = fs.readFileSync(__dirname + '/data/' + filename, 'utf8');
        return Bluebird.resolve(response.trim());
    });

    done();
});

after(function (done) {
    mockery.disable();
    mockery.deregisterAll();
    done();
});

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
    });
});

Based on that you may now build a more sophisticated mock. Sinon.js may be of help as well.

Contributing

To set up your development environment:

  1. clone the repo to your desktop,
  2. in the shell cd to the main folder,
  3. hit npm install,
  4. hit npm install gulp -g if you haven't installed gulp globally yet, and
  5. run gulp dev. (Or run node ./node_modules/.bin/gulp dev if you don't want to install gulp globally.)

gulp dev watches all source files and if you save some changes it will lint the code and execute all tests. The test coverage report can be viewed from ./coverage/lcov-report/index.html.

If you want to debug a test you should use gulp test-without-coverage to run all tests without obscuring the code by the test coverage instrumentation.

Change History

  • v4.2.6 (2020-07-21)
    • Security fix: bumped request-promise-core which bumps lodash to ^4.17.19 following this advisory.
  • v4.2.5 (2019-11-03)
    • Security fix: bumped request-promise-core which bumps lodash to ^4.17.15. See vulnerabilty reports. (Thanks to @rishabh-chowdhary for reporting this in pull request #326.)
  • v4.2.4 (2019-02-14)
    • Corrected mistakenly set tough-cookie version, now ^2.3.3 (Thanks to @evocateur for pointing this out.)
    • If you installed [email protected] please make sure after the upgrade that request and request-promise use the same physical copy of tough-cookie.
  • v4.2.3 (2019-02-14)
    • Using stricter tough-cookie@~2.3.3 to avoid installing tough-cookie@3 which introduces breaking changes (Thanks to @aomdoa for pull request #299)
    • Security fix: bumped lodash to ^4.17.11, see vulnerabilty reports
  • v4.2.2 (2017-09-22)
    • Upgraded tough-cookie to a version without regex DoS vulnerability (Thanks to @rouanw for pull request #226)
  • v4.2.1 (2017-05-07)
  • v4.2.0 (2017-03-16)
  • v4.1.1 (2016-08-08)
    • Renamed internally used package @request/promise-core to request-promise-core because there where too many issues with the scoped package name (Thanks to @cabrinoob, @crazy4groovy, @dsandor, @KpjComp, @lorenwest, @Reisyukaku, @tehChromic, @todd for providing helpful information.)
  • v4.1.0 (2016-07-30)
  • v4.0.2 (2016-07-18)
    • Fix for using with module bundlers like Webpack and Browserify
  • v4.0.1 (2016-07-17)
    • Fixed @request/promise-core version for safer versioning
  • v4.0.0 (2016-07-15)
    • Breaking Change: request is declared as a peer dependency which has to be installed separately by the user now
    • Breaking Change: Dropped support for Continuation Local Storage since request-promise-any can be used for that now
    • Introduced the transform2xxOnly option to ease the breaking change regarding the new transform handling in v3.0.0 (Thanks to @stevage for pointing out the effect of the breaking change in issue #131)
    • Resolved issues #65 and #71 by publishing nearly identical libraries to support other Promise implementations: request-promise-native and request-promise-any (Thanks to @benjamingr, @eilgin, @gillesdemey, @hildjj, @iggycoloma, @jonathanong, @knpwrs, @MarkHerhold, @massimocode, @mikeal, @niftylettuce, @raitucarp, @sherdeadlock, @tonylukasavage, and @vgoloviznin for the valuable discussions!)
    • Relicensed this library with the ISC license
  • v3.0.0 (2016-04-16)
    • Breaking Change: Overhauled the handling of the transform function (Thanks to @Limess for explaining the need in issue #86)
    • Breaking Change: Updated bluebird to v3 (Thanks to @BrandonSmith for pull request #103)
    • Improved StatusCodeError.message
    • Updated lodash to v4.6
    • Improved README in regard to .catch(...) best practice (Thanks to @RebootJeff for pull request #98)
  • v2.0.1 (2016-02-17)
  • v2.0.0 (2016-01-12)
    • Breaking Change: Removed explicit cls-bluebird dependency which has to be installed by the user now (Thanks to @hildjj for his pull request #75)
    • npm shrinkwrap now works for npm@3 users who don't use continuation-local-storage (Thanks to @toboid and @rstacruz for reporting the issue in issue #70 and issue #82)
  • v1.0.2 (2015-10-22)
    • Removed continuation-local-storage from peer dependencies as it was unnecessary (Thanks to @mrhyde for working on a better solution discussed in issue #70)
  • v1.0.1 (2015-10-14)
    • Fixed a npm warning by marking continuation-local-storage as a peer dependency
  • v1.0.0 (2015-10-11)
    • Breaking 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)
    • Breaking Change: Request-Promise does not load its own Bluebird prototype anymore. If you use Bluebird in your project and altered the prototype then Request-Promise may use your altered Bluebird prototype internally.
    • 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)
    • Extended transform function by a third resolveWithFullResponse parameter
    • Added experimental support for continuation local storage (Thanks to @silverbp preparing this in issue #64)
    • Added node.js 4 to the Travis CI build
    • Updated the README (Thanks to many people for their feedback in issues #55 and #59)
  • v0.4.3 (2015-07-27)
    • Reduced overhead by just requiring used lodash functions instead of the whole lodash library (Thanks to @luanmuniz for pull request #54)
    • Updated dependencies
  • v0.4.2 (2015-04-12)
    • Updated dependencies
  • v0.4.1 (2015-03-20)
    • Improved Error types to work in browsers without v8 engine (Thanks to @nodiis for pull request #40)
  • v0.4.0 (2015-02-08)
    • Introduced Error types used for the reject reasons (See last part this section) (Thanks to @jakecraige for starting the discussion in issue #38)
    • Minor Breaking 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 and node.js 0.12 to the Travis CI build
  • v0.3.3 (2015-01-19)
    • Fixed handling possibly unhandled rejections to work with the latest version of Bluebird (Thanks to @slang800 for reporting this in issue #36)
  • v0.3.2 (2014-11-17)
    • Exposed .finally(...) to allow using it as the first method in the promise chain (Thanks to @hjpbarcelos for his pull request #28)
  • v0.3.1 (2014-11-11)
    • Added the .promise() method for advanced Bluebird API usage (Thanks to @devo-tox for his feedback in issue #27)
  • v0.3.0 (2014-11-10)
    • Carefully rewritten from scratch to make Request-Promise a drop-in replacement for Request

License (ISC)

In case you never heard about the ISC license it is functionally equivalent to the MIT license.

See the LICENSE file for details.

request-promise's People

Contributors

analog-nico avatar courajs avatar cwinters avatar erf avatar evancarroll avatar floatdrop avatar graingert avatar hbarcelos avatar hildjj avatar jmm avatar jtwb2 avatar kukat avatar lexjacobs avatar luanmuniz avatar nodiis avatar not-an-aardvark avatar raineorshine avatar ratson avatar rebootjeff avatar rouanw avatar servel333 avatar shisama avatar syrok avatar tyabonil avatar yamsellem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

request-promise's Issues

Is there retry logic for bad connections?

Just wondering if the library itself has a utility flag/method or someone has a gist for retrying requests automatically?

For example, usecases like:

  1. 429 based rate limiting might require pause and retry
  2. connection timeout might require a retry

HEAD call useless without resolveWithFullResponse

As a HEAD call is a GET call without response body, it's pretty useless without the resolveWithFullResponse option, as you get an empty string all the time.

I personally would vote for having res.headers as the default parameter passed to .head() calls, or to at least set resolveWithFullResponse to true by default.

Or is it intended to preserve the same behavior in all convenience functions, even if it's nonsense to a particular function?

How do you handle error responses properly?

So I'm using request-promise in a script that I have that loops through a list of urls and fires of requests. then I want to do something w/ the data received once all the requests are complete.

I have the following:

var rp = require('request-promise');

rp.get({
            uri: 'http://httpstat.us/500',
            transform: function(body, res){
                res.data = JSON.parse(body);
                return res;
            }
        }).then(function(res){
            results.push(res.data);
        })
        .catch(function(err){
            should.throw.error.to.console();
            var respErr  = JSON.parse(err.error);
            var errorResult = {
                origUrl: respErr.origUrl,
                error: respErr
            };
            results.push(errorResult);
        });

As you can see.. http://httpstat.us/500 throws a 500, which causes the .catch() block to be ran. I'm forcing an error. should.throw.error.to.console(); should throw an error to the console, but instead, the script just exits silently w/o any error code (Process finished with exit code 0).

I'm assuming that you're catching the error from node's http when a page doesn't come back w/ 2xx code and then passing that back to the catch() callback. But any subsequent errors then end up failing silently. How in the world do I handle this so that the rest of my code will still throw errors properly?

New Updated Code Breaks Promise Functions

This was meant to be a combination of both request and bluebird.

But now with the API changes you will no longer be able to use any of bluebird's methods other than .then and .catch.Especially one as useful as .bind(this).

Question: Will you be somehow proxying methods to Bluebird in an upcoming release or is this the way you will go from now on just adding prototyp methods directly to the request object?

Using request promise

Just to want to know best way to use rp below is a partial sample request structure that we have now.

Im trying out rp, do you have suggestion how this can be modified to make it better

request(option1, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        var data= JSON.parse(body);

        if(data.valid){

            if(data.expired){

                next();
            }else{

                request(option2, function (error2, response2, body2) {
                    var data2= JSON.parse(body2);
                    if(data2.valid) {
                        request(option3, function (error3, response3, body3) {
                            next();
                        })
                    } else {
                        res.json({success:false});
                    }
                })

            }
        }else{
            res.json({success:false});
        }
    }else{
        res.json({success:false});
    }
})

export `RequestError` and `StatusCodeError`

Since I want to reliably detect what type of error occured, I need to check err in the error handler using err instanceof โ€ฆ. This is only possible if request-promise exports the constructors. Please do so.

timeout option not working

So I set up the following:

var rp = require('request-promise');

var start = Date.now();
var reqPromise = rp({
    method: 'get',
    uri: 'http://localhost:8080/test-connection-length',
    timeout: 600000, // 10 min.
    resolveWithFullResponse: true
});

var interval = setInterval(function(){
    console.log('Waiting: ', (Date.now() - start) / 1000);
}, 1000);

reqPromise.then(function(resp){
    console.log('got response: ', resp);
})
.catch(function(err){
    console.error(err.toString());
    console.error(err.stack);
})
.finally(function(){
        console.log('Done: ', (Date.now() - start) / 1000);
    clearInterval(interval);
});

The test server endpoint just sits and doesn't respond, writing a similar console log every second as well.

Even though I have a 10min timeout set, the result is the following in the client:

Waiting:  116.464
Waiting:  117.469
Waiting:  118.475
RequestError: Error: socket hang up
RequestError: Error: socket hang up
Waiting:  119.481
    at new RequestError (/Users/matthewmarcus/WebStormProjects/CaptoraInc/capture-site-validation/node_modules/request-promise/lib/errors.js:11:15)
Done:  120.03
    at Request.RP$callback [as _callback] (/Users/matthewmarcus/WebStormProjects/CaptoraInc/capture-site-validation/node_modules/request-promise/lib/rp.js:50:34)
    at self.callback (/Users/matthewmarcus/WebStormProjects/CaptoraInc/capture-site-validation/node_modules/request-promise/node_modules/request/request.js:197:22)
    at Request.emit (events.js:107:17)
    at Request.onRequestError (/Users/matthewmarcus/WebStormProjects/CaptoraInc/capture-site-validation/node_modules/request-promise/node_modules/request/request.js:854:8)
    at ClientRequest.emit (events.js:107:17)
    at Socket.socketOnEnd (_http_client.js:300:9)
    at Socket.emit (events.js:129:20)
    at _stream_readable.js:908:16
    at process._tickCallback (node.js:355:11)

Process finished with exit code 0

Shouldn't this happen at 10mins, not 2?

Possibly unhandled StatusCodeError: 400

When i receive the StatusCode 400 from a server i have this error

Possibly unhandled StatusCodeError: 400 - { errorMessage: "Unable to complete Request", errorCode: 1 }
    at new StatusCodeError (/api/node_modules/request-promise/lib/errors.js:26:15)
    at Request.RP$callback [as _callback] (/api/node_modules/request-promise/lib/rp.js:58:34)
    at Request.self.callback (/api/node_modules/request/request.js:360:22)
    at Request.emit (events.js:110:17)
    at Request.<anonymous> (/api/node_modules/request/request.js:1202:14)
    at Request.emit (events.js:129:20)
    at IncomingMessage.<anonymous> (/api/node_modules/request/request.js:1150:12)
    at IncomingMessage.emit (events.js:129:20)
    at _stream_readable.js:908:16
    at process._tickCallback (node.js:355:11)

Should i post this issue at the request module?

How to handle cookies?

Hi!
Before of using this lib, I was using the non-promise version of request, where I was able to send into a GET also some cookies, as the follow:

var j = req.jar();
var url = "my_url";
var cookie = req.cookie("" + mycookie);
j.setCookie(cookie, url);
req({ uri: url, method: "GET", jar: j }, function(....));

By now with the same options, but using promise-request, I'm getting an error into catch function, saying just this:
[SyntaxError: Unexpected token u]

Am I missing something?
Thanks in advance!

Can this be used in client side ?

Is there any way for this package to be used in client side ?
I'm looking for a non-jquery node module to be used in client-side, and pack it via webpack.
This module seemed to be good but the requirement of fs doesn't let webpack to work with it.

Is there any workaround for this ? or any way to just load enough scripts for client side to pack ?

post param

Dear,
Is it possible to add a post parameter ? I couldn't find a way to add them and couldn't find neither a test nor an example.

Possible to stub with sinon.js?

Hello,

I'm trying to stub request-promise using sinon, however could not find a way yet on how to do that.
Back when i was using request itself, it looked something like this:

before(function (done) {
        sinon.stub(request, 'get').yields(null, { statusCode: 200 }, fs.readFileSync(__dirname + '/data/' + filename));
        done();
    });

    after(function (done) {
        request.get.restore();
        done();
    });
}

Any suggestions on how to do this with promise-request?
Feel free to close this issue if it doesn't fit in here.

Async transfrom via promise

Is it possible to let transform be able to resolve a promise? like this:

options.transform = function (data) {
  return new Promise(function(resolve) {
    setTimeout(function() { resolve(1); }, 1);
  });
};

rp(options)
    .then(function(res) {
      // `res` will be `1`
    });

Error when using request methods

Calling rp.post() results in:

ReferenceError: key is not defined

See rp.js, Line 122:

function getParams(){
    var args = Array.prototype.slice.call(arguments, 0);
    var params = request.initParams.apply(request, args);
    params.method = methodNameLookup[key];
    return params;
}

Parameter uri not being set from parameter url

This is a 0.2.x specific bug.
I have installed the following components:

[email protected] node_modules/request-promise
โ”œโ”€โ”€ [email protected]
โ””โ”€โ”€ [email protected]

If I try like this:

'use strict';

var rp = require('request-promise');
var options = {
    url: 'http://google.com.br',
};

rp.get(options)
.then(function(response){
    console.log(response);
}).catch(function(reason){
    console.log(reason);
});

I get the following reason logged:

Error: options.uri is a required argument

However, if I change url to uri, it works just as expected.

These two parameters should relfect each other.

Use Case: Wrap `pipe` events in promises

Thank you for putting this awesome abstraction together!

I came across a use case recently where I wanted to .pipe an arbitrary number of request results to my file system and .then finish my grunt task.

I would have loved to accomplish this via an abstraction of your library, I was wondering if you would consider looking at this use case and adding it out-of-the-box to your lib by wrapping pipe events in promises?

I accomplished it like so:

    var done = this.async();
    ...
          var downloaded = []; // make sure all the download pipes finish - step # 1
          var _ = require('underscore');
          var fs = require('fs');
          // GET for each resource
          _.each(paths, function(path){
            var filename = './downloded' + path + '.json';
            console.log(filename);
            var r = request
              .get(path)
              .on('error', function(err) {
                console.log(err);
                done();
              })
              // save in a file
              .pipe(fs.createWriteStream(filename));

            // make sure all the download pipes finish  - step # 2
            downloaded.push(
              new Promise(function (resolve, reject) {
                r.on('finish', function () {
                  console.log('pipe finished');
                  return resolve();
                });
              })
            );
          });

          // make sure all the download pipes finish - step # 3
          Promise.all(downloaded).then(function() {
            console.log('all the files were downloaded');
            done();
          });

Invalid URI should cause the promise to be rejected

var rq = require('request-promise');

rq('test').then(function(){
  console.log('success');
})
.catch(function(err){
  console.log('failed')
});

Expects the code to log 'failed' on console but instead throws error

CLS and Promises

Is there a way to patch this so CLS works inside the Promises without having to fork and patch the entire thing with cls-bluebird?

qs doesn't work

in the options object using

qs: { some: 'query' }

should append a ?some=query to the end of the request

How to handle an error in the body

Hey guys

I have this peculiar requirement to check the body for an error object, since the API that I'm working with will return a status code of 200 along with an error object in the body.

200 OK
{
  "error": "shitty API's error response"
}

Is there an easy way to define what should trigger an error, preferably using the defaults setting so that I can keep the codebase clean and DRY.

I've read up on the simple options, however I'm not sure of it's the right way to go.

In addition, I was hoping to use the transform function to reject the promise however the promise itself is not accessible from within the function?

Unless it's accessible in the transform using something like

this.promise().reject();

Thanks

Weird issue when using Promise.settle w/ array of request-promises using `.finally()`

I have an array of request-promises that I am sending to Promise.settle, in each of these promises I am using the .finally() method and doing a return Promise.resolve(some_val); yet when I inspect my resolved value in the settle resolution, the Bluebird value() method returns undefined.

This seems to resolve itself if I move returning a new Promise inside my catch or then on the original request-promise.

doesn't work:

...
var req = rq('http://failing_domain_doesnt_resolve.com')
    .then(function(){})
    .catch(function(err){ // this gets called ok })
    .finally(function() {
         return Promise.resolve('I am ok!');
    });

Promise.settle([req])
    .then(function(results) {
        console.info(results[0].value()); // undefined
     });

Thanks for your work on this!

404 triggers then() instead of error()

During testing I've found that 404 responses are still resolved instead of rejected if no parameters except uri are set. As response only receives the body this can't even be noticed.
Imho- except from fixing this- it might make more sense to reply with the same parameters as the request module itself to make this lib more of a drop-in replacement.

Travis CI integration

Hi @tyabonil

I just added the .travis.yml so that Travis CI can build this project. This is especially helpful when we get a pull request because Travis CI then builds the sources as if the pull request was pulled in and reports the result to the pull request page.

All you need to do is to:

  1. sign in to Travis CI with your GitHub account,
  2. go to your profile page, and
  3. switch on the switch for this repository.

Thats it! Thanks!

What's considered "large quantities of data"

In the docs you write "If you stream large quantities of data 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."

Have you done any test on this and is it possible to state in the docs where the typical limit is? Or is it too dependent on environment so that it's up to everyone to test ourselves?

Make a POST request with data on request body

I looked into the documentation and didnt find anything about it.

I'm wondering if I can make a POST passing the parameters into the body instead as a query string.

Is that possible?

error with nw.js

$ nw .
Possibly unhandled Error: TypeError: Illegal invocation
    at Object.ensureErrorObject (/Users/username/projects/rank/node_modules/request-promise/node_modules/bluebird/js/main/util.js:228:20)
    at Promise._rejectCallback (/Users/username/projects/rank/node_modules/request-promise/node_modules/bluebird/js/main/promise.js:416:22)
    at Promise._settlePromiseFromHandler (/Users/username/projects/rank/node_modules/request-promise/node_modules/bluebird/js/main/promise.js:460:17)
    at Promise._settlePromiseAt (/Users/username/projects/rank/node_modules/request-promise/node_modules/bluebird/js/main/promise.js:530:18)
    at Promise._settlePromises (/Users/username/projects/rank/node_modules/request-promise/node_modules/bluebird/js/main/promise.js:646:14)
    at Async._drainQueue (/Users/username/projects/rank/node_modules/request-promise/node_modules/bluebird/js/main/async.js:164:16)
    at Async._drainQueues (/Users/username/projects/rank/node_modules/request-promise/node_modules/bluebird/js/main/async.js:174:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/Users/username/projects/rank/node_modules/request-promise/node_modules/bluebird/js/main/async.js:15:14)
    at processImmediate [as _immediateCallback] (timers.js:321:17)

Here's my code:

var rp = require('request-promise');

rp('http://www.google.com')
    .then(console.dir)
    .catch(console.error);

POST request that results in 302 triggers catch

var request = require('request-promise');

request({
    url: 'http://httpstat.us/302',
    method: 'POST'
})
    .catch(function (error) {
        console.log(error);
    })
    .then(function () {
        console.log('OK')
    });

The error is just the incomingMessage object:

{ error: '302 Found',
  options:
   { method: 'POST',
     url: 'http://httpstat.us/302',
     callback: undefined,
     uri: undefined,
     tunnel: false,
     simple: true,
     resolveWithFullResponse: false },
  response:
   { _readableState:
      { objectMode: false,
        highWaterMark: 16384,
        buffer: [],
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: true,
        endEmitted: true,
        reading: false,
        sync: true,
        needReadable: false,
        emittedReadable: false,
        readableListening: false,
        defaultEncoding: 'utf8',
        ranOut: false,
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null,
        resumeScheduled: false },
     readable: false,
     domain: null,
     _events:
      { end: [Object],
        close: [Object],
        data: [Function],
        error: [Function] },
     _maxListeners: undefined,
     socket:
      { _connecting: false,
        _hadError: false,
        _handle: null,
        _host: 'httpstat.us',
        _readableState: [Object],
        readable: false,
        domain: null,
        _events: [Object],
        _maxListeners: 0,
        _writableState: [Object],
        writable: false,
        allowHalfOpen: false,
        destroyed: true,
        bytesRead: 422,
        _bytesDispatched: 79,
        _pendingData: null,
        _pendingEncoding: '',
        parser: null,
        _httpMessage: [Object],
        read: [Function],
        _consuming: true,
        _idleNext: null,
        _idlePrev: null,
        _idleTimeout: -1 },
     connection:
      { _connecting: false,
        _hadError: false,
        _handle: null,
        _host: 'httpstat.us',
        _readableState: [Object],
        readable: false,
        domain: null,
        _events: [Object],
        _maxListeners: 0,
        _writableState: [Object],
        writable: false,
        allowHalfOpen: false,
        destroyed: true,
        bytesRead: 422,
        _bytesDispatched: 79,
        _pendingData: null,
        _pendingEncoding: '',
        parser: null,
        _httpMessage: [Object],
        read: [Function],
        _consuming: true,
        _idleNext: null,
        _idlePrev: null,
        _idleTimeout: -1 },
     httpVersionMajor: 1,
     httpVersionMinor: 1,
     httpVersion: '1.1',
     complete: true,
     headers:
      { 'cache-control': 'private',
        'content-length': '9',
        'content-type': 'text/plain; charset=utf-8',
        location: 'http://httpstat.us',
        server: 'Microsoft-IIS/8.0',
        'x-aspnetmvc-version': '5.1',
        'x-aspnet-version': '4.0.30319',
        'x-powered-by': 'ASP.NET',
        'set-cookie': [Object],
        date: 'Thu, 08 Jan 2015 15:52:34 GMT',
        connection: 'close' },
     rawHeaders:
      [ 'Cache-Control',
        'private',
        'Content-Length',
        '9',
        'Content-Type',
        'text/plain; charset=utf-8',
        'Location',
        'http://httpstat.us',
        'Server',
        'Microsoft-IIS/8.0',
        'X-AspNetMvc-Version',
        '5.1',
        'X-AspNet-Version',
        '4.0.30319',
        'X-Powered-By',
        'ASP.NET',
        'Set-Cookie',
        'ARRAffinity=0289d9a2e779a2431db31b4a154e84828a77f89dbbe1fe391d5fe9794f54f970;Path=/;Domain=httpstat.us',
        'Date',
        'Thu, 08 Jan 2015 15:52:34 GMT',
        'Connection',
        'close' ],
     trailers: {},
     rawTrailers: [],
     _pendings: [],
     _pendingIndex: 0,
     upgrade: false,
     url: '',
     method: null,
     statusCode: 302,
     statusMessage: 'Found',
     client:
      { _connecting: false,
        _hadError: false,
        _handle: null,
        _host: 'httpstat.us',
        _readableState: [Object],
        readable: false,
        domain: null,
        _events: [Object],
        _maxListeners: 0,
        _writableState: [Object],
        writable: false,
        allowHalfOpen: false,
        destroyed: true,
        bytesRead: 422,
        _bytesDispatched: 79,
        _pendingData: null,
        _pendingEncoding: '',
        parser: null,
        _httpMessage: [Object],
        read: [Function],
        _consuming: true,
        _idleNext: null,
        _idlePrev: null,
        _idleTimeout: -1 },
     _consuming: true,
     _dumped: false,
     req:
      { domain: null,
        _events: [Object],
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: false,
        _removedHeader: [Object],
        _hasBody: true,
        _trailer: '',
        finished: true,
        _hangupClose: false,
        socket: [Object],
        connection: [Object],
        agent: [Object],
        socketPath: undefined,
        method: 'POST',
        path: '/302',
        _headers: [Object],
        _headerNames: [Object],
        _header: 'POST /302 HTTP/1.1\r\nhost: httpstat.us\r\ncontent-length: 0\r\nConnection: close\r\n\r\n',
        _headerSent: true,
        parser: null,
        res: [Circular] },
     request:
      { domain: null,
        _events: [Object],
        _maxListeners: undefined,
        uri: [Object],
        callback: [Function],
        method: 'POST',
        readable: true,
        writable: true,
        explicitMethod: true,
        canTunnel: false,
        _rp_resolve: [Function],
        _rp_reject: [Function],
        _rp_promise: [Object],
        _rp_callbackOrig: undefined,
        _rp_options: [Object],
        headers: [Object],
        setHeader: [Function],
        hasHeader: [Function],
        getHeader: [Function],
        removeHeader: [Function],
        localAddress: undefined,
        qsLib: [Object],
        pool: {},
        dests: [],
        __isRequestRequest: true,
        _callback: [Function: RP$callback],
        proxy: null,
        tunnel: false,
        _redirectsFollowed: 0,
        maxRedirects: 10,
        allowRedirect: [Function],
        followRedirects: true,
        followAllRedirects: false,
        redirects: [],
        setHost: true,
        originalCookieHeader: undefined,
        _disableCookies: true,
        _jar: undefined,
        port: 80,
        host: 'httpstat.us',
        path: '/302',
        httpModule: [Object],
        agentClass: [Object],
        agent: [Object],
        _rp_promise_in_use: true,
        _started: true,
        href: 'http://httpstat.us/302',
        req: [Object],
        ntick: true,
        response: [Circular],
        originalHost: 'httpstat.us',
        originalHostHeaderName: 'host',
        _destdata: true,
        _ended: true,
        _callbackCalled: true },
     toJSON: [Function: responseToJSON],
     caseless: { dict: [Object] },
     read: [Function],
     body: '302 Found' },
  statusCode: 302 }

Lodash error using request promise

While making a get request, I get the following error

"Uncaught TypeError: _.assign is not a function", source: /Users/ZECTbynmo/Projects/ConnectorTester/node_modules/request-promise/lib/rp.js (19)

Any ideas?

Undefined header value yields an error that cannot be handled

I am using request-promise and I got a mysterious error:

Uncought exception Error: `value` required in setHeader("cookie", value).
at ClientRequest.OutgoingMessage.setHeader (_http_outgoing.js:339:11)
at new ClientRequest (_http_client.js:80:14)
at Object.exports.request (http.js:31:10)
at Request.start (/opt/myapp/webapp/lib/app/frontend/node_modules/request/request.js:904:30)
at Request.end (/opt/myapp/webapp/lib/app/frontend/node_modules/request/request.js:1635:10)
at end (/opt/myapp/webapp/lib/app/frontend/node_modules/request/request.js:676:14)
at Immediate._onImmediate (/opt/myapp/webapp/lib/app/frontend/node_modules/request/request.js:690:7)
at processImmediate [as _immediateCallback] (timers.js:374:17)

seems that if you do a:

rp({
  uri: 'http://localhost:60000/some/route',
  method: 'GET',
  resolveWithFullResponse: true,
  headers: {
    cookie: undefined
  }
});

you will get an exception that cannot be handled

Aligning on a jshintrc

Hi Ty, I just committed the gulp integration. I loosened the settings in the .jshintrc so no changes to the sources were needed. The following rules could be activated again (but would need small changes in the code):

  1. curly (Require {} for every new block or scope.)
  2. latedef (Prohibit variable use before definition.)
  3. strict (Require use strict pragma in every file.)
  4. asi (Do not tolerate Automatic Semicolon Insertion (no semicolons).)
  5. sub (Do not tolerate all forms of subscript notation besides dot notation e.g. dict['key'] instead of dict.key.)
  6. Remove Promise global (See: jshint/jshint#1747)

I usually have all but number 5 activated. How would you like to configure it?

poor error message

When an error occurs in a request, I get this printed out (directly after whatever error message I print for the error):

/usrdata/web/facebook-insights-cli/node_modules/request-promise/node_modules/bluebird/js/main/async.js:36
        fn = function () { throw arg; };
                                 ^
TypeError: undefined is not a function
  at module.exports (/usrdata/web/facebook-insights-cli/node_modules/request-promise/lib/rp.js:158:9)
  at Function.CapturedTrace.fireRejectionEvent (/usrdata/web/facebook-insights-cli/node_modules/request-promise/node_modules/bluebird/js/main/captured_trace.js:214:17)
  at Promise._notifyUnhandledRejection (/usrdata/web/facebook-insights-cli/node_modules/request-promise/node_modules/bluebird/js/main/promise.js:889:23)
  at Async._drainQueue (/usrdata/web/facebook-insights-cli/node_modules/request-promise/node_modules/bluebird/js/main/async.js:84:12)
  at Async._drainQueues (/usrdata/web/facebook-insights-cli/node_modules/request-promise/node_modules/bluebird/js/main/async.js:91:10)
  at Async.drainQueues (/usrdata/web/facebook-insights-cli/node_modules/request-promise/node_modules/bluebird/js/main/async.js:14:14)
  at process._tickCallback (node.js:419:13)

...which isn't very helpful.

[Question] Get result for new request

I need results from request promise then() after, and use again result for new request ?? How do that?
I hope, have someone support my question. Thanks !

   let opt = {
        method: 'POST',
        uri: API,
        body: {
            news_id: id
        },
        json: true
    };

    rp(opt).then(function (result) {
        rpt(opt2).then(function () { // error
        })
    })

timeout

Is there a way to set the timeout for the request?

Reject with an error object

I ran into a problem when using this with mocha. The problem is because when rejecting, this library returns a JS object instead of an Error object. I'd like to open up discussion for changing it to return an error object instead. The options can still be put on there for introspection purposes, but I think it makes more sense to reject with a true Error.

From what I can tell, this is where it happens: https://github.com/tyabonil/request-promise/blob/master/lib/rp.js#L48-L58 and you have tests ensuring this is the case here

Issue also reported to mocha: mochajs/mocha#1532

error when importing request-promise

I have installed request-promise via npm

npm i --save request-promise

Then I import it into a file:

import rq from 'request-promise'

Now I get this message:

ERROR in ./~/request-promise/~/request/lib/har.js
Module not found: Error: Cannot resolve module 'fs' in C:\Users\alex\ae\node_modules\request-promise\node_modules\reques
t\lib
 @ ./~/request-promise/~/request/lib/har.js 3:9-22

ERROR in ./~/request-promise/~/request/~/forever-agent/index.js
Module not found: Error: Cannot resolve module 'net' in C:\Users\alex\ae\node_modules\request-promise\node_modules\reque
st\node_modules\forever-agent
 @ ./~/request-promise/~/request/~/forever-agent/index.js 6:10-24

ERROR in ./~/request-promise/~/request/~/forever-agent/index.js
Module not found: Error: Cannot resolve module 'tls' in C:\Users\alex\ae\node_modules\request-promise\node_modules\reque
st\node_modules\forever-agent
 @ ./~/request-promise/~/request/~/forever-agent/index.js 7:10-24

ERROR in ./~/request-promise/~/request/~/tough-cookie/lib/cookie.js
Module not found: Error: Cannot resolve module 'net' in C:\Users\alex\ae\node_modules\request-promise\node_modules\reque
st\node_modules\tough-cookie\lib
 @ ./~/request-promise/~/request/~/tough-cookie/lib/cookie.js 32:10-24

ERROR in ./~/request-promise/~/request/~/tunnel-agent/index.js
Module not found: Error: Cannot resolve module 'net' in C:\Users\alex\ae\node_modules\request-promise\node_modules\reque
st\node_modules\tunnel-agent
 @ ./~/request-promise/~/request/~/tunnel-agent/index.js 3:10-24

ERROR in ./~/request-promise/~/request/~/tunnel-agent/index.js
Module not found: Error: Cannot resolve module 'tls' in C:\Users\alex\ae\node_modules\request-promise\node_modules\reque
st\node_modules\tunnel-agent
 @ ./~/request-promise/~/request/~/tunnel-agent/index.js 4:10-24

ERROR in ./~/request-promise/~/request/~/har-validator/~/is-my-json-valid/~/jsonpointer/jsonpointer.js
Module not found: Error: Cannot resolve module 'console' in C:\Users\alex\ae\node_modules\request-promise\node_modules\r
equest\node_modules\har-validator\node_modules\is-my-json-valid\node_modules\jsonpointer
 @ ./~/request-promise/~/request/~/har-validator/~/is-my-json-valid/~/jsonpointer/jsonpointer.js 1:14-32

This is my package.json, just in case:

{
  "name": "ae",
  "version": "1.0.0",
  "description": "arteigenschaften.ch",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server",
    "prebuild": "gulp cleanPublic",
    "build": "set NODE_ENV=production&& webpack",
    "test": "standard"
  },
  "author": "Alexander Gabriel",
  "license": "ISC",
  "dependencies": {
    "ampersand-app": "1.0.4",
    "ampersand-router": "3.0.2",
    "autolinker": "0.18.1",
    "autoprefixer-core": "5.2.1",
    "babel": "5.6.23",
    "babel-loader": "5.3.2",
    "bootstrap": "3.3.5",
    "classnames": "2.1.3",
    "css-loader": "0.15.5",
    "del": "1.2.0",
    "file-loader": "0.8.4",
    "gulp": "3.9.0",
    "hjs-webpack": "2.10.0",
    "jquery": "2.1.4",
    "json-loader": "0.5.2",
    "local-links": "1.4.0",
    "lodash": "3.10.0",
    "node-libs-browser": "0.5.2",
    "postcss-loader": "0.5.1",
    "pouchdb": "3.6.0",
    "pouchdb-all-dbs": "^1.0.1",
    "pouchdb-load": "^1.4.0",
    "react": "0.13.3",
    "react-bootstrap": "0.23.7",
    "react-favicon": "0.0.3",
    "react-hot-loader": "1.2.8",
    "react-json-inspector": "5.1.0",
    "react-textarea-autosize": "2.4.0",
    "react-typeahead": "^1.1.1",
    "reflux": "0.2.10",
    "request-promise": "^0.4.2",
    "require-dir": "0.3.0",
    "style-loader": "0.12.3",
    "stylus-loader": "1.2.1",
    "surge": "0.14.3",
    "url-loader": "0.5.6",
    "webpack": "1.10.1",
    "webpack-dev-server": "1.10.1",
    "yeticss": "7.0.1"
  },
  "standard": {
    "ignore": [
      "public/*"
    ]
  }
}

Failing test

Currently the last test (resolveWithFullResponse should include the response) is failing.

The reason for the failure is that the options object still contains uri: 'http://localhost:4000/500' from a preceding test (simple tests should reject for 500 status code). Since the test sets url instead of uri both properties are set and request uses the uri in the end.

To solve this the options objects should be properly initialized for each call without producing such side effects.

Please let me know if I should do the fix.

No standard error object?

Why aren't you returning a standard error object?

rp("http://google.com/foobar")
    .then(console.dir)
    .catch( function(err) {
        //err should be a standard error object but is just "404"
        console.error("logging error", err);
        throw err;
    });

Error thrown on 3xx HTTP status

Possibly unhandled StatusCodeError: 302 - 
    at new StatusCodeError (/[...]/node_modules/request-promise/lib/errors.js:26:15)
    at Request.RP$callback [as _callback] (/[...]/node_modules/request-promise/lib/rp.js:64:32)
    at Request.self.callback (/[...]/node_modules/request/request.js:198:22)
    at emitTwo (events.js:87:13)
    at Request.emit (events.js:172:7)
    at Request.<anonymous> (/[...]/node_modules/request/request.js:1063:14)
    at emitOne (events.js:82:20)
    at Request.emit (events.js:169:7)
    at IncomingMessage.<anonymous> (/[...]/node_modules/request/request.js:1009:12)
    at emitNone (events.js:72:20)
    at IncomingMessage.emit (events.js:166:7)
    at endReadableNT (_stream_readable.js:893:12)
    at doNTCallback2 (node.js:429:9)
    at process._tickCallback (node.js:343:17)

This makes followRedirect set to false unusable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.