Comparing version 0.5.6 to 0.5.7
233
index.js
"use strict"; | ||
var P = require('bluebird'); | ||
var url = require('url'); | ||
var util = require('util'); | ||
var querystring = require('querystring'); | ||
var semver = require('semver'); | ||
const P = require('bluebird'); | ||
const url = require('url'); | ||
const querystring = require('querystring'); | ||
const request = require('requestretry'); | ||
function createConnectTimeoutAgent(protocol) { | ||
var http = require(protocol); | ||
var Agent = http.Agent; | ||
const http = require(`${protocol}`); | ||
// Many concurrent connections to the same host | ||
function ConnectTimeoutAgent() { | ||
Agent.apply(this, arguments); | ||
} | ||
util.inherits(ConnectTimeoutAgent, Agent); | ||
if (semver.gte(process.version, '5.7.0')) { | ||
ConnectTimeoutAgent.prototype.createSocket = function(req, options, cb) { | ||
var connectTimeoutTimer = setTimeout(function() { | ||
var e = new Error('ETIMEDOUT'); | ||
class ConnectTimeoutAgent extends http.Agent { | ||
createSocket(req, options, cb) { | ||
const connectTimeoutTimer = setTimeout(() => { | ||
const e = new Error('ETIMEDOUT'); | ||
e.code = 'ETIMEDOUT'; | ||
cb(e); | ||
}, this.options.connectTimeout); | ||
Agent.prototype.createSocket.apply(this, [req, options, function(error, newSocket) { | ||
newSocket.on('connect', function() { | ||
super.createSocket(req, options, (error, newSocket) => { | ||
newSocket.on('connect', () => { | ||
clearTimeout(connectTimeoutTimer); | ||
}); | ||
cb(error, newSocket); | ||
}]); | ||
}; | ||
} else { | ||
ConnectTimeoutAgent.prototype.createSocket = function() { | ||
var s = Agent.prototype.createSocket.apply(this, arguments); | ||
// Set up a connect timeout if connectTimeout option is set | ||
if (this.options.connectTimeout && !s.connectTimeoutTimer) { | ||
s.connectTimeoutTimer = setTimeout(function () { | ||
var e = new Error('ETIMEDOUT'); | ||
e.code = 'ETIMEDOUT'; | ||
s.end(); | ||
s.emit('error', e); | ||
s.destroy(); | ||
}, this.options.connectTimeout); | ||
s.once('connect', function () { | ||
if (this.connectTimeoutTimer) { | ||
clearTimeout(this.connectTimeoutTimer); | ||
this.connectTimeoutTimer = undefined; | ||
} | ||
}); | ||
} | ||
return s; | ||
}; | ||
}); | ||
} | ||
} | ||
return ConnectTimeoutAgent; | ||
} | ||
var defaultAgentOptions = { | ||
const defaultAgentOptions = { | ||
connectTimeout: (process.env.PREQ_CONNECT_TIMEOUT || 5) * 1000, | ||
@@ -66,7 +39,5 @@ // Setting this too high (especially 'Infinity') leads to high | ||
}; | ||
var httpAgentClass = createConnectTimeoutAgent('http'); | ||
var httpsAgentClass = createConnectTimeoutAgent('https'); | ||
const httpAgentClass = createConnectTimeoutAgent('http'); | ||
const httpsAgentClass = createConnectTimeoutAgent('https'); | ||
var request = P.promisify(require('request'), { multiArgs: true }); | ||
function getOptions(uri, o, method) { | ||
@@ -78,3 +49,3 @@ if (!o || o.constructor !== Object) { | ||
} else { | ||
o = { uri: uri }; | ||
o = { uri }; | ||
} | ||
@@ -90,3 +61,3 @@ } else { | ||
o.headers = o.headers || {}; | ||
Object.keys(o.headers).forEach(function(header) { | ||
Object.keys(o.headers).forEach((header) => { | ||
if (header.toLowerCase() !== header) { | ||
@@ -107,5 +78,7 @@ o.headers[header.toLowerCase()] = o.headers[header]; | ||
if ((o.method === 'get' || o.method === 'put') | ||
&& o.retries === undefined) { | ||
&& o.retries === undefined) { | ||
// Idempotent methods: Retry once by default | ||
o.retries = 1; | ||
o.maxAttempts = 2; | ||
} else { | ||
o.maxAttempts = o.retries + 1; | ||
} | ||
@@ -123,3 +96,4 @@ | ||
if ((o.headers && /\bgzip\b/.test(o.headers['accept-encoding'])) || (o.gzip === undefined && o.method === 'get')) { | ||
if ((o.headers && /\bgzip\b/.test(o.headers['accept-encoding'])) | ||
|| (o.gzip === undefined && o.method === 'get')) { | ||
o.gzip = true; | ||
@@ -146,15 +120,14 @@ } | ||
*/ | ||
function HTTPError(response) { | ||
Error.call(this); | ||
Error.captureStackTrace(this, HTTPError); | ||
this.name = this.constructor.name; | ||
this.message = response.status.toString(); | ||
if (response.body && response.body.type) { | ||
this.message += ': ' + response.body.type; | ||
class HTTPError extends Error { | ||
constructor(response) { | ||
super(); | ||
Error.captureStackTrace(this, HTTPError); | ||
this.name = this.constructor.name; | ||
this.message = response.status.toString(); | ||
if (response.body && response.body.type) { | ||
this.message += `: ${response.body.type}`; | ||
} | ||
Object.assign(this, response); | ||
} | ||
for (var key in response) { | ||
this[key] = response[key]; | ||
} | ||
} | ||
util.inherits(HTTPError, Error); | ||
@@ -165,42 +138,28 @@ | ||
*/ | ||
function Request (method, url, options) { | ||
this.options = getOptions(url, options, method); | ||
this.retries = this.options.retries; | ||
this.timeout = this.options.timeout; | ||
this.delay = 100; // start with 100ms | ||
} | ||
Request.prototype.retry = function (err) { | ||
if (this.retries) { | ||
this.retries--; | ||
// exponential backoff with some fuzz, but start with a short delay | ||
this.delay = this.delay * 2 + this.delay * Math.random(); | ||
// grow the timeout linearly, plus some fuzz | ||
this.timeout += this.options.timeout + Math.random() * this.options.timeout; | ||
return P.bind(this) | ||
.delay(this.delay) | ||
.then(this.run); | ||
} else { | ||
throw err; | ||
class Request { | ||
constructor(method, url, options) { | ||
this.options = getOptions(url, options, method); | ||
this.delay = 100; // start with 100ms | ||
this.options.delayStrategy = () => { | ||
// exponential backoff with some fuzz, but start with a short delay | ||
const delay = this.delay; | ||
this.delay = this.delay * 2 + this.delay * Math.random(); | ||
return delay; | ||
}; | ||
this.options.promiseFactory = resolver => new P(resolver); | ||
this.options.retryStrategy = (err, response) => { | ||
if (response && response.statusCode === 503 | ||
&& /^[0-9]+$/.test(response.headers['retry-after'])) { | ||
this.delay = parseInt(response.headers['retry-after'], 10) * 1000; | ||
return true; | ||
} | ||
return request.RetryStrategies.HTTPOrNetworkError(err, response); | ||
}; | ||
} | ||
}; | ||
Request.prototype.run = function () { | ||
var self = this; | ||
return P.try(function() { return request(self.options) }) | ||
.bind(this) | ||
.then(function(responses) { | ||
if (!responses || responses.length < 2) { | ||
return this.retry(new HTTPError({ | ||
status: 502, | ||
body: { | ||
type: 'empty_response', | ||
} | ||
})); | ||
} else { | ||
var response = responses[0]; | ||
var body = responses[1]; // decompressed | ||
if (self.options.gzip && response.headers) { | ||
run() { | ||
return request(this.options) | ||
.then((response) => { | ||
let body = response.body; | ||
if (this.options.gzip && response.headers) { | ||
delete response.headers['content-encoding']; | ||
@@ -210,4 +169,4 @@ delete response.headers['content-length']; | ||
if (body && response.headers && !self.options._encodingProvided) { | ||
var contentType = response.headers['content-type']; | ||
if (body && response.headers && !this.options._encodingProvided) { | ||
const contentType = response.headers['content-type']; | ||
// Decodes: "text/...", "application/json...", "application/vnd.geo+json..." | ||
@@ -227,20 +186,20 @@ if (/^text\/|application\/([^+;]+\+)?json\b/.test(contentType)) { | ||
if (response.statusCode === 204 || response.statusCode === 205 | ||
|| response.statusCode === 304) { | ||
|| response.statusCode === 304) { | ||
body = undefined; | ||
} | ||
var res = { | ||
const res = { | ||
status: response.statusCode, | ||
headers: response.headers, | ||
body: body | ||
body | ||
}; | ||
// Check if we were redirected | ||
var origURI = self.options.uri; | ||
if (self.options.qs && Object.keys(self.options.qs).length) { | ||
origURI += '?' + querystring.stringify(self.options.qs); | ||
let origURI = this.options.uri; | ||
if (this.options.qs && Object.keys(this.options.qs).length) { | ||
origURI += `?${querystring.stringify(this.options.qs)}`; | ||
} | ||
if (origURI !== response.request.uri.href | ||
&& url.format(origURI) !== response.request.uri.href) { | ||
&& url.format(origURI) !== response.request.uri.href) { | ||
if (!res.headers['content-location']) { | ||
@@ -254,3 +213,3 @@ // Indicate the redirect via an injected Content-Location | ||
res.headers['content-location'] = url.parse(response.request.uri) | ||
.resolve(res.headers['content-location']); | ||
.resolve(res.headers['content-location']); | ||
} | ||
@@ -260,9 +219,2 @@ } | ||
if (res.status >= 400) { | ||
if (res.status === 503 | ||
&& /^[0-9]+$/.test(response.headers['retry-after']) | ||
&& parseInt(response.headers['retry-after']) * 1000 < self.options.timeout) { | ||
self.delay = parseInt(response.headers['retry-after']) * 1000; | ||
return self.retry(new HTTPError(res)); | ||
} | ||
throw new HTTPError(res); | ||
@@ -272,32 +224,29 @@ } else { | ||
} | ||
} | ||
}, | ||
function (err) { | ||
return this.retry(new HTTPError({ | ||
status: 504, | ||
body: { | ||
type: 'internal_http_error', | ||
description: err.toString(), | ||
error: err, | ||
stack: err.stack, | ||
uri: self.options.uri, | ||
method: self.options.method, | ||
}, | ||
stack: err.stack | ||
})); | ||
}); | ||
}; | ||
}, (err) => { | ||
throw new HTTPError({ | ||
status: err.status || 504, | ||
body: { | ||
type: 'internal_http_error', | ||
description: err.toString(), | ||
error: err, | ||
stack: err.stack, | ||
uri: this.options.uri, | ||
method: this.options.method, | ||
}, | ||
stack: err.stack | ||
}); | ||
}); | ||
} | ||
} | ||
var preq = function preq (url, options) { | ||
var method = (options || url || {}).method || 'get'; | ||
const preq = (url, options) => { | ||
const method = (options || url || {}).method || 'get'; | ||
return new Request(method, url, options).run(); | ||
}; | ||
var methods = ['get','head','put','post','delete','trace','options','mkcol','patch']; | ||
methods.forEach(function(method) { | ||
preq[method] = function (url, options) { | ||
return new Request(method, url, options).run(); | ||
}; | ||
const methods = ['get', 'head', 'put', 'post', 'delete', 'trace', 'options', 'mkcol', 'patch']; | ||
methods.forEach((method) => { | ||
preq[method] = (url, options) => new Request(method, url, options).run(); | ||
}); | ||
module.exports = preq; |
{ | ||
"name": "preq", | ||
"version": "0.5.6", | ||
"version": "0.5.7", | ||
"description": "Yet another promising request wrapper", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "mocha && nsp check" | ||
"test": "mocha && nsp check", | ||
"coverage": "istanbul cover _mocha -- -R spec", | ||
"coveralls": "cat ./coverage/lcov.info | coveralls" | ||
}, | ||
"author": "Gabriel Wicke <gwicke@wikimedia.org>", | ||
"license": "MIT", | ||
"engines": { | ||
"node": ">=6.0.0" | ||
}, | ||
"dependencies": { | ||
"bluebird": "^3.1.1", | ||
"request": "^2.85.0", | ||
"semver": "^5.5.0" | ||
"bluebird": "^3.5.2", | ||
"request": "^2.88.0", | ||
"requestretry": "^3.0.2" | ||
}, | ||
"devDependencies": { | ||
"mocha": "^5.0.4", | ||
"coveralls": "^3.0.2", | ||
"eslint-config-node-services": "^2.2.5", | ||
"eslint-config-wikimedia": "^0.8.1", | ||
"eslint-plugin-jsdoc": "^3.9.1", | ||
"eslint-plugin-json": "^1.2.1", | ||
"eslint": "^5.8.0", | ||
"istanbul": "^0.4.5", | ||
"mocha": "^5.2.0", | ||
"mocha-eslint": "^4.1.0", | ||
"mocha-lcov-reporter": "^1.3.0", | ||
"nock": "^10.0.1", | ||
"nsp": "^3.2.1" | ||
@@ -19,0 +34,0 @@ }, |
@@ -1,50 +0,131 @@ | ||
var preq = require('../index'); | ||
var assert = require('assert'); | ||
'use strict'; | ||
// mocha defines to avoid JSHint breakage | ||
/* global describe, it, before, beforeEach, after, afterEach */ | ||
const nock = require('nock'); | ||
const zlib = require('zlib'); | ||
const preq = require('../index'); | ||
const assert = require('assert'); | ||
require('mocha-eslint')([ '.' ]); | ||
describe('preq', function() { | ||
this.timeout(30000); | ||
it('should retry', function() { | ||
var tStart = new Date(); | ||
this.timeout(30000); // eslint-disable no-invalid-this | ||
it('throws with undefined options', () => | ||
assert.throws(() => preq(), Error, 'Must throw if options not provided')); | ||
it('should retry', () => { | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.times(5) | ||
.reply(504, ''); | ||
const tStart = new Date(); | ||
return preq.get({ | ||
// Some unreachable port | ||
uri: 'http://localhost:1/', | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
retries: 4 | ||
}) | ||
.catch(function(e) { | ||
.catch((e) => { | ||
assert.equal(e.status, 504); | ||
var tDelta = new Date() - tStart; | ||
if (tDelta < 3150) { | ||
const tDelta = new Date() - tStart; | ||
if (tDelta < 1000) { | ||
throw new Error("Does not look as if this actually retried!"); | ||
} | ||
}); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('get enwiki front page', function() { | ||
it('should not retry 404', () => { | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.reply(404, ''); | ||
const tStart = new Date(); | ||
return preq.get({ | ||
// Some unreachable port | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
retries: 4 | ||
}) | ||
.then(function(res) { | ||
.catch((e) => { | ||
assert.equal(e.status, 404); | ||
const tDelta = new Date() - tStart; | ||
if (tDelta > 1000) { | ||
throw new Error("Looks like this was actually retried!"); | ||
} | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('should respect retry-after', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.reply(503, '', { 'retry-after': 3 }) | ||
.get('/wiki/Main_Page') | ||
.reply(200, MOCK_BODY); | ||
const tStart = new Date(); | ||
return preq.get({ | ||
// Some unreachable port | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
retries: 1 | ||
}) | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(res.body, MOCK_BODY); | ||
const tDelta = new Date() - tStart; | ||
if (tDelta < 2500) { | ||
throw new Error("retry-after was not respected"); | ||
} | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('should get enwiki front page', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.reply(200, MOCK_BODY); | ||
return preq.get({ | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
}) | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(!!res.body, true); | ||
// Make sure content-location is not set | ||
assert.equal(!!res.headers['content-location'], false); | ||
}); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('get google.com, check for redirect', function() { | ||
it('should check for redirect', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/') | ||
.reply(301, undefined, { location: 'https://en.wikipedia.org/wiki/Main_Page' }) | ||
.get('/wiki/Main_Page') | ||
.reply(200, MOCK_BODY); | ||
return preq.get({ | ||
uri: 'https://en.wikipedia.org/', | ||
retries: 2 | ||
uri: 'https://en.wikipedia.org/' | ||
}) | ||
.then(function(res) { | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(!!res.body, true); | ||
assert.equal(res.headers['content-location'], | ||
'https://en.wikipedia.org/wiki/Main_Page'); | ||
}); | ||
'https://en.wikipedia.org/wiki/Main_Page'); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('get google.com with query', function() { | ||
it('should support query', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.query({ q : 'foo' }) | ||
.reply(200, MOCK_BODY); | ||
return preq.get({ | ||
uri: 'http://google.com/', | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
query: { | ||
@@ -54,18 +135,33 @@ q: 'foo' | ||
}) | ||
.then(function(res) { | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(!!res.body, true); | ||
}); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('get google.com, simple constructor style', function() { | ||
return preq('http://google.com/') | ||
.then(function(res) { | ||
it('should support simple constructor style', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.reply(200, MOCK_BODY); | ||
return preq('https://en.wikipedia.org/wiki/Main_Page') | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(!!res.body, true); | ||
}); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('get google.com with query, constructor style', function() { | ||
it('should support simple constructor style with query', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.query({ q : 'foo' }) | ||
.reply(200, MOCK_BODY); | ||
return preq({ | ||
method: 'get', | ||
uri: 'http://google.com/', | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
query: { | ||
@@ -75,31 +171,164 @@ q: 'foo' | ||
}) | ||
.then(function(res) { | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(!!res.body, true); | ||
}); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('return buffer on user-supplied encoding', function() { | ||
return preq('http://google.com/', {encoding: null}) | ||
.then(function(res) { | ||
it('return buffer on user-supplied encoding', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.reply(200, MOCK_BODY); | ||
return preq('https://en.wikipedia.org/wiki/Main_Page', { encoding: null }) | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(res.body.constructor.name, 'Buffer'); | ||
}); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('return string with no encoding', function() { | ||
return preq('http://google.com/') | ||
.then(function(res) { | ||
assert.equal(res.status, 200); | ||
assert.equal(typeof res.body, 'string'); | ||
}); | ||
}); | ||
it('no content-encoding header for gzipped responses', function() { | ||
it('no content-encoding header for gzipped responses', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.reply(200, zlib.gzipSync(Buffer.from(MOCK_BODY)), { 'content-encoding': 'gzip' }); | ||
return preq({ | ||
uri: 'https://en.wikipedia.org/api/rest_v1/page/html/Foobar', | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
gzip: true | ||
}).then(function(res) { | ||
}) | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(res.headers['content-encoding'], undefined); | ||
}); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('parse json', () => { | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.reply(200, { test: 'test' }, { 'content-type': 'application/json' }); | ||
return preq('https://en.wikipedia.org/wiki/Main_Page') | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(res.body.test, 'test'); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('resolve relative redirects', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/') | ||
.reply(301, undefined, { 'location': '/wiki/Main_Page' }) | ||
.get('/wiki/Main_Page') | ||
.reply(200, MOCK_BODY, { 'content-location': '/wiki/Main_Page' }); | ||
return preq('https://en.wikipedia.org') | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(res.headers['content-location'], | ||
'https://en.wikipedia.org/wiki/Main_Page'); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('remove body for 204 requests', () => { | ||
const api = nock('https://en.wikipedia.org') | ||
.get('/wiki/Main_Page') | ||
.reply(204, "SOME_ERRORNEOUS_BODY"); | ||
return preq('https://en.wikipedia.org/wiki/Main_Page') | ||
.then((res) => { | ||
assert.equal(res.status, 204); | ||
assert.equal(res.body, undefined); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('lowecase request headers', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const api = nock('https://en.wikipedia.org', { | ||
reqheaders: { | ||
'cache-control': 'no-cache', | ||
'x-request-id': 'test_id' | ||
} | ||
}) | ||
.get('/wiki/Main_Page') | ||
.reply(200, MOCK_BODY); | ||
return preq({ | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
headers: { | ||
'Cache-Control': 'no-cache', | ||
'x-request-id': 'test_id' | ||
} | ||
}) | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('sends JSON', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const MOCK_REQ = { test: 'test' }; | ||
const api = nock('https://en.wikipedia.org') | ||
.post('/wiki/Main_Page', JSON.stringify(MOCK_REQ)) | ||
.reply(200, MOCK_BODY); | ||
return preq({ | ||
method: 'post', | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
headers: { | ||
'content-type': 'application/json' | ||
}, | ||
body: MOCK_REQ | ||
}) | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('sends form', () => { | ||
const MOCK_BODY = 'Main_Wiki_Page_HTML'; | ||
const MOCK_REQ = { test: 'test' }; | ||
const api = nock('https://en.wikipedia.org') | ||
.post('/wiki/Main_Page', 'test=test') | ||
.reply(200, MOCK_BODY); | ||
return preq({ | ||
method: 'post', | ||
uri: 'https://en.wikipedia.org/wiki/Main_Page', | ||
body: MOCK_REQ | ||
}) | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(res.body, MOCK_BODY); | ||
}) | ||
.then(() => api.done()) | ||
.finally(() => nock.cleanAll()); | ||
}); | ||
it('request some real content, no nock', () => preq('https://en.wikipedia.org/wiki/Main_Page') | ||
.then((res) => { | ||
assert.equal(res.status, 200); | ||
assert.equal(!!res.body, true); | ||
})); | ||
it('timeout with connect timeout', () => preq({ | ||
uri: 'http://localhost:12345', | ||
connectTimeout: 1 | ||
}) | ||
.catch(e => assert.equal(e.status, 504))); | ||
}); | ||
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
22872
9
522
12
1
+ Addedrequestretry@^3.0.2
+ Addedlodash@4.17.21(transitive)
+ Addedrequestretry@3.1.0(transitive)
+ Addedwhen@3.7.8(transitive)
- Removedsemver@^5.5.0
- Removedsemver@5.7.2(transitive)
Updatedbluebird@^3.5.2
Updatedrequest@^2.88.0