Socket
Socket
Sign inDemoInstall

then-request

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

then-request - npm Package Compare versions

Comparing version 0.0.4 to 1.0.0

lib/handle-qs.js

96

browser.js
'use strict';
var Promise = require('promise');
var Response = require('request-shared/lib/response');
var Response = require('http-response-object');
var handleQs = require('./lib/handle-qs.js');
module.exports = doRequest;
function doRequest(uri, options) {
return new Promise(function (resolve, reject) {
function doRequest(method, url, options, callback) {
var result = new Promise(function (resolve, reject) {
var xhr = new window.XMLHttpRequest();
// 1 - handle variable list of arguments
if (typeof uri === 'undefined') {
throw new TypeError('undefined is not a valid uri or options object.');
// check types of arguments
if (typeof method !== 'string') {
throw new TypeError('The method must be a string.');
}
if (options && typeof options === 'object') {
options.uri = uri;
} else if (typeof uri === 'string') {
options = {uri: uri};
} else {
options = uri;
if (typeof url !== 'string') {
throw new TypeError('The URL/path must be a string.');
}
options = copy(options);
if (options.url && !options.uri) {
options.uri = options.url;
delete options.url;
if (typeof options === 'function') {
callback = options;
options = {};
}
if (options === null || options === undefined) {
options = {};
}
if (typeof options !== 'object') {
throw new TypeError('Options must be an object (or null).');
}
if (typeof callback !== 'function') {
callback = undefined;
}
method = method.toUpperCase();
options.headers = options.headers || {};
// 2 - handle cross domain option
if (!options.crossDomain) {
var match;
options.crossDomain = !!((match = /^([\w-]+:)?\/\/([^\/]+)/.exec(options.uri)) &&
(match[2] != window.location.host));
// handle cross domain
var match;
var crossDomain = !!((match = /^([\w-]+:)?\/\/([^\/]+)/.exec(options.uri)) && (match[2] != window.location.host));
if (!crossDomain) options.headers['X-Requested-With'] = 'XMLHttpRequest';
// handle query string
if (options.qs) {
url = handleQs(url, options.qs);
}
if (!options.crossDomain) options.headers['X-Requested-With'] = 'XMLHttpRequest';
options.method = (options.method || 'GET').toUpperCase();
// handle json body
if (options.json) {
options.body = JSON.stringify(options.json);
options.headers['content-type'] = 'application/json';
}
xhr.onreadystatechange = function () {

@@ -51,5 +67,6 @@ if (xhr.readyState === 4) {

};
// type, uri, async
xhr.open(options.method, options.uri, true);
// method, url, async
xhr.open(method, url, true);
for (var name in options.headers) {

@@ -62,27 +79,6 @@ xhr.setRequestHeader(name.toLowerCase(), options.headers[name]);

});
result.getBody = function () {
return result.then(function (res) { return res.getBody(); });
};
return result.nodeify(callback);
}
function copy(obj, seen) {
seen = seen || [];
if (seen.indexOf(obj) !== -1) {
throw new Error('Unexpected circular reference in options');
}
seen.push(obj);
if (Array.isArray(obj)) {
return obj.map(function (item) {
return copy(item, seen);
});
} else if (obj && typeof obj === 'object') {
var o = {}
Object.keys(obj).forEach(function (i) {
o[i] = copy(obj[i], seen)
})
return o
} else {
return obj;
}
}
function empty() {
}
'use strict';
var parseUrl = require('url').parse;
var Promise = require('promise');
var Request = require('request-shared').Request;
var Response = require('request-shared').Response;
var concat = require('concat-stream');
var protocols = {
http: require('http'),
https: require('https')
};
var Response = require('http-response-object');
var handleQs = require('./lib/handle-qs.js');
module.exports = doRequest;
function doRequest(url, options) {
return new Promise(function (resolve, reject) {
var request = new Request(url, options);
if (['http', 'https'].indexOf(request.protocol) === -1) {
throw new Error('Invalid protocol ' + request.protocol);
module.exports._request = require('http-basic');
function doRequest(method, url, options, callback) {
var result = new Promise(function (resolve, reject) {
// check types of arguments
if (typeof method !== 'string') {
throw new TypeError('The method must be a string.');
}
var http = protocols[request.protocol];
delete request.protocol;
var req = http.request(request, function (res) {
var body = '';
res.once('error', reject);
res.pipe(concat(function (body) {
if (typeof url !== 'string') {
throw new TypeError('The URL/path must be a string.');
}
if (typeof options === 'function') {
callback = options;
options = {};
}
if (options === null || options === undefined) {
options = {};
}
if (typeof options !== 'object') {
throw new TypeError('Options must be an object (or null).');
}
if (typeof callback !== 'function') {
callback = undefined;
}
method = method.toUpperCase();
options.headers = options.headers || {};
// handle query string
if (options.qs) {
url = handleQs(url, options.qs);
}
// handle json body
if (options.json) {
options.body = JSON.stringify(options.json);
options.headers['content-type'] = 'application/json';
}
var req = module.exports._request(method, url, {
headers: options.headers,
followRedirects: true,
gzip: true,
cache: options.cache
}, function (err, res) {
if (err) return reject(err);
res.body.on('error', reject);
res.body.pipe(concat(function (body) {
resolve(new Response(res.statusCode, res.headers, Array.isArray(body) ? new Buffer(0) : body));
}));
});
req.once('error', reject);
req.end(request.body);
if (req) {
req.end(options.body ? options.body : new Buffer(0));
}
});
}
result.getBody = function (encoding) {
return result.then(function (res) { return res.getBody(encoding); });
};
return result.nodeify(callback);
}
{
"name": "then-request",
"version": "0.0.4",
"version": "1.0.0",
"description": "A request library that returns promises, inspired by request",

@@ -8,14 +8,14 @@ "keywords": [],

"dependencies": {
"request-shared": "0.0.1",
"promise": "~3.2.0",
"concat-stream": "~1.4.1"
"promise": "^5.0.0",
"concat-stream": "^1.4.1",
"qs": "^0.6.6",
"http-response-object": "^1.0.1",
"http-basic": "^1.0.2"
},
"devDependencies": {
"chromedriver": "~2.8.1",
"cabbie": "0.0.5",
"run-browser": "~1.2.0"
"testit": "^1.2.0",
"istanbul": "^0.3.0"
},
"scripts": {
"test": "node test/server.js & node test/index.js",
"test-browser": "node test/server.js & run-browser tests/index.js"
"test": "node test/index.js && istanbul cover test/index.js"
},

@@ -22,0 +22,0 @@ "repository": {

@@ -13,4 +13,59 @@ # then-request

## Usage
`request(method, url, options, callback?)`
e.g.
```js
request('GET', 'http://example.com').done(function (res) {
console.log(res.getBody());
});
```
**Method:**
An HTTP method (e.g. `GET`, `POST`, `PUT`, `DELETE` or `HEAD`). It is not case sensitive.
**URL:**
A url as a string (e.g. `http://example.com`). Relative URLs are allowed in the browser.
**Options:**
- `qs` - an object containing querystring values to be appended to the uri
- `headers` - http headers (default: `{}`)
- `body` - body for PATCH, POST and PUT requests. Must be a `Buffer` or `String` (only strings are accepted client side)
- `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json`. Does not have any affect on how the response is treated.
- `cache` - only used in node.js (browsers already have their own caches) Can be `'memory'`, `'file'` or your own custom implementaton (see https://github.com/ForbesLindesay/http-basic#implementing-a-cache).
**Callback / Returns:**
If a callback is provided it is called with `err` and `res`. If no callback is provided, a [Promise](https://www.promisejs.org/) is returned that eventually resolves to `res`. The resulting Promise also has an additional `.getBody(encoding?)` method that is equivallent to calling `.then(function (res) { return res.getBody(); })`.
### Response
Note that even for status codes that represent an error, the promise will be resolved as the request succeeded. You can call `getBody` if you want to error on invalid status codes. The response has the following properties:
- `statusCode` - a number representing the HTTP status code
- `headers` - http response headers
- `body` - a string if in the browser or a buffer if on the server
It also has a method `getBody(encoding?)` which looks like:
```js
function getBody(encoding) {
if (this.statusCode >= 300) {
var err = new Error('Server responded with status code ' + this.statusCode + ':\n' + this.body.toString(encoding));
err.statusCode = this.statusCode;
err.headers = this.headers;
err.body = this.body;
throw err;
}
return encoding ? this.body.toString(encoding) : this.body;
}
```
## License
MIT
'use strict';
var assert = require('assert');
var request = require('../');
var test = require('testit');
module.exports = request('http://localhost:3000/foo', {method: 'POST'})
.then(function (res) {
assert(res.statusCode === 200);
assert(res.headers);
assert(res.headers['my-header'] === 'value');
assert(res.body);
test('./lib/handle-qs.js', function () {
var handleQs = require('../lib/handle-qs.js');
assert(handleQs('http://example.com/', {foo: 'bar'}) === 'http://example.com/?foo=bar');
assert(handleQs('http://example.com/', {foo: {bar: 'baz'}}) === 'http://example.com/?foo[bar]=baz');
assert(handleQs('http://example.com/', {foo: 'bar', bing: 'bong'}) === 'http://example.com/?foo=bar&bing=bong');
assert(handleQs('http://example.com/?foo=bar', {bing: 'bong'}) === 'http://example.com/?foo=bar&bing=bong');
assert(handleQs('http://example.com/?foo=bar#ding', {bing: 'bong'}) === 'http://example.com/?foo=bar&bing=bong#ding');
});
module.exports.done(function () {
if (typeof window !== 'undefined') {
window.testsPassed = true;
}
console.log('tests passed');
}, function (err) {
if (typeof window !== 'undefined') {
window.testsPassed = false;
}
console.log('tests failed');
throw err;
});
require('./browser.js');
require('./server.js');
function testEnv(env) {
var request = require(env === 'browser' ? '../browser.js' : '../index.js');
test(env + ' - GET', function () {
return request('GET', 'http://example.com').then(function (res) {
assert(res.statusCode === 200);
assert(res.headers['foo'] === 'bar');
assert(res.body.toString() === 'body');
});
});
test(env + ' - GET query', function () {
return request('GET', 'http://example.com', {qs: {foo: 'baz'}}).then(function (res) {
assert(res.statusCode === 200);
assert(res.headers['foo'] === 'baz');
assert(res.body.toString() === 'body');
});
});
test(env + ' - GET -> .getBody("utf8")', function () {
return request('GET', 'http://example.com').getBody('utf8').then(function (body) {
assert(body === 'body');
});
});
test(env + ' - POST json', function () {
return request('POST', 'http://example.com', {json: {foo: 'baz'}}).then(function (res) {
assert(res.statusCode === 200);
assert(res.body.toString() === 'json body');
});
});
test(env + ' - invalid method', function () {
return request({}, 'http://example.com').then(function (res) {
throw new Error('Expected an error');
}, function (err) {
assert(err instanceof TypeError);
});
});
test(env + ' - invalid url', function () {
return request('GET', {}).then(function (res) {
throw new Error('Expected an error');
}, function (err) {
assert(err instanceof TypeError);
});
});
test(env + ' - invalid options', function () {
return request('GET', 'http://example.com', 'options').then(function (res) {
throw new Error('Expected an error');
}, function (err) {
assert(err instanceof TypeError);
});
});
}
testEnv('browser');
testEnv('server');
'use strict';
var http = require('http');
var fs = require('fs');
var crypto = require('crypto');
var runBrowser = require('run-browser');
var concat = require('concat-stream');
var util = require('util');
var assert = require('assert');
var PassThrough = require('stream').PassThrough;
var getResponse = require('./get-mock-response.js');
var handler = runBrowser.createHandler(require.resolve('./index.js'));
var resultHandlers = [];
function onResult(pass) {
for (var i = 0; i < resultHandlers.length; i++) {
resultHandlers[i](pass);
require('../index.js')._request = function (method, url, options, callback) {
assert(typeof callback === 'function');
var duplex = !(method === 'GET' || method === 'DELETE' || method === 'HEAD');
if (duplex) {
return {
end: function (body) {
gotResponse(getResponse(method, url, options.headers, body, {isClient: false}));
}
};
} else {
gotResponse(getResponse(method, url, options.headers, null, {isClient: false}));
}
}
var server = http.createServer(function (req, res) {
if (runBrowser.handles(req)) {
return handler(req, res);
function gotResponse(res) {
var stream = new PassThrough();
stream.end(res.body);
res.body = stream;
callback(null, res);
}
if (req.url === '/result/pass') {
onResult(true);
res.end();
}
if (req.url === '/result/fail') {
onResult(false);
res.end();
}
res.setHeader('My-Header', 'value');
if (req.url === '/204') {
req = {
httpVersion: req.httpVersion,
headers: req.headers,
method: req.method,
url: req.url
};
// console.log(util.inspect(req, {colors: true}).replace(/^/gm, ' '));
res.statusCode = 204;
return res.end();
}
req.pipe(concat(function (body) {
req = {
httpVersion: req.httpVersion,
headers: req.headers,
method: req.method,
url: req.url,
body: body
};
// console.log(util.inspect(req, {colors: true}).replace(/^/gm, ' '));
var shasum = crypto.createHash('sha1');
shasum.update(req.httpVersion);
shasum.update(req.headers['host'] || '');
shasum.update(req.headers['headers-a'] || '');
shasum.update(req.headers['headers-b'] || '');
shasum.update(req.headers['authorization'] || '');
shasum.update(req.headers['accept'] || '');
shasum.update(req.headers['content-type'] || '');
shasum.update(req.headers['content-length'] || '');
shasum.update(req.headers['transfer-encoding'] || '');
shasum.update(req.url);
shasum.update(req.body);
res.end(shasum.digest('hex'));
}));
});
server.listen(3000);
module.exports.close = function () {
server.close();
};
module.exports.on = function (name, fn) {
if (name === 'result') {
resultHandlers.push(fn);
}
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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