Skip to content

Commit 15afe79

Browse files
committed
Added .auth, .jar and .cookie implementations along with corresponding tests
1 parent a8ba27b commit 15afe79

File tree

4 files changed

+200
-155
lines changed

4 files changed

+200
-155
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ node_modules
22
npm-debug.log
33
.env
44
coverage
5+
.vscode
6+
package-lock.json

index.js

Lines changed: 158 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ var RetryStrategies = require('./strategies');
1414
var _ = require('lodash');
1515

1616
var DEFAULTS = {
17-
maxAttempts: 5, // try 5 times
18-
retryDelay: 5000, // wait for 5s before trying again
19-
fullResponse: true, // resolve promise with the full response object
20-
promiseFactory: defaultPromiseFactory // Function to use a different promise implementation library
17+
maxAttempts: 5, // try 5 times
18+
retryDelay: 5000, // wait for 5s before trying again
19+
fullResponse: true, // resolve promise with the full response object
20+
promiseFactory: defaultPromiseFactory // Function to use a different promise implementation library
2121
};
2222

2323
// Default promise factory which use bluebird
2424
function defaultPromiseFactory(resolver) {
25-
return when.promise(resolver);
25+
return when.promise(resolver);
2626
}
2727

2828
/**
@@ -34,189 +34,193 @@ function defaultPromiseFactory(resolver) {
3434
*/
3535
function makePromise(requestInstance, promiseFactoryFn) {
3636

37-
// Resolver function wich assigns the promise (resolve, reject) functions
38-
// to the requestInstance
39-
function Resolver(resolve, reject) {
40-
this._resolve = resolve;
41-
this._reject = reject;
42-
}
37+
// Resolver function wich assigns the promise (resolve, reject) functions
38+
// to the requestInstance
39+
function Resolver(resolve, reject) {
40+
this._resolve = resolve;
41+
this._reject = reject;
42+
}
4343

44-
return promiseFactoryFn(Resolver.bind(requestInstance));
44+
return promiseFactoryFn(Resolver.bind(requestInstance));
4545
}
4646

4747
function Request(url, options, f, retryConfig) {
48-
// ('url')
49-
if(_.isString(url)){
50-
// ('url', f)
51-
if(_.isFunction(options)){
52-
f = options;
48+
// ('url')
49+
if (_.isString(url)) {
50+
// ('url', f)
51+
if (_.isFunction(options)) {
52+
f = options;
53+
}
54+
55+
if (!_.isObject(options)) {
56+
options = {};
57+
}
58+
59+
// ('url', {object})
60+
options.url = url;
5361
}
5462

55-
if(!_.isObject(options)){
56-
options = {};
63+
if (_.isObject(url)) {
64+
if (_.isFunction(options)) {
65+
f = options;
66+
}
67+
options = url;
5768
}
5869

59-
// ('url', {object})
60-
options.url = url;
61-
}
62-
63-
if(_.isObject(url)){
64-
if(_.isFunction(options)){
65-
f = options;
66-
}
67-
options = url;
68-
}
69-
70-
this.maxAttempts = retryConfig.maxAttempts;
71-
this.retryDelay = retryConfig.retryDelay;
72-
this.fullResponse = retryConfig.fullResponse;
73-
this.attempts = 0;
74-
75-
/**
76-
* Option object
77-
* @type {Object}
78-
*/
79-
this.options = options;
80-
81-
/**
82-
* Return true if the request should be retried
83-
* @type {Function} (err, response) -> Boolean
84-
*/
85-
this.retryStrategy = _.isFunction(options.retryStrategy) ? options.retryStrategy : RetryStrategies.HTTPOrNetworkError;
86-
87-
/**
88-
* Return a number representing how long request-retry should wait before trying again the request
89-
* @type {Boolean} (err, response, body) -> Number
90-
*/
91-
this.delayStrategy = _.isFunction(options.delayStrategy) ? options.delayStrategy : function() { return this.retryDelay; };
92-
93-
this._timeout = null;
94-
this._req = null;
95-
96-
this._callback = _.isFunction(f) ? _.once(f) : null;
97-
98-
// create the promise only when no callback was provided
99-
if (!this._callback) {
100-
this._promise = makePromise(this, retryConfig.promiseFactory);
101-
}
102-
103-
this.reply = function requestRetryReply(err, response, body) {
104-
if (this._callback) {
105-
return this._callback(err, response, body);
70+
this.maxAttempts = retryConfig.maxAttempts;
71+
this.retryDelay = retryConfig.retryDelay;
72+
this.fullResponse = retryConfig.fullResponse;
73+
this.attempts = 0;
74+
75+
/**
76+
* Option object
77+
* @type {Object}
78+
*/
79+
this.options = options;
80+
81+
/**
82+
* Return true if the request should be retried
83+
* @type {Function} (err, response) -> Boolean
84+
*/
85+
this.retryStrategy = _.isFunction(options.retryStrategy) ? options.retryStrategy : RetryStrategies.HTTPOrNetworkError;
86+
87+
/**
88+
* Return a number representing how long request-retry should wait before trying again the request
89+
* @type {Boolean} (err, response, body) -> Number
90+
*/
91+
this.delayStrategy = _.isFunction(options.delayStrategy) ? options.delayStrategy : function () {
92+
return this.retryDelay;
93+
};
94+
95+
this._timeout = null;
96+
this._req = null;
97+
98+
this._callback = _.isFunction(f) ? _.once(f) : null;
99+
100+
// create the promise only when no callback was provided
101+
if (!this._callback) {
102+
this._promise = makePromise(this, retryConfig.promiseFactory);
106103
}
107104

108-
if (err) {
109-
return this._reject(err);
110-
}
105+
this.reply = function requestRetryReply(err, response, body) {
106+
if (this._callback) {
107+
return this._callback(err, response, body);
108+
}
109+
110+
if (err) {
111+
return this._reject(err);
112+
}
111113

112-
// resolve with the full response or just the body
113-
response = this.fullResponse ? response : body;
114-
this._resolve(response);
115-
};
114+
// resolve with the full response or just the body
115+
response = this.fullResponse ? response : body;
116+
this._resolve(response);
117+
};
116118
}
117119

118120
Request.request = request;
119121

120122
Request.prototype._tryUntilFail = function () {
121-
this.maxAttempts--;
122-
this.attempts++;
123-
124-
this._req = Request.request(this.options, function (err, response, body) {
125-
if (response) {
126-
response.attempts = this.attempts;
127-
}
128-
if (this.retryStrategy(err, response, body) && this.maxAttempts > 0) {
129-
this._timeout = setTimeout(this._tryUntilFail.bind(this), this.delayStrategy.call(this, err, response, body));
130-
return;
131-
}
132-
133-
this.reply(err, response, body);
134-
}.bind(this));
123+
this.maxAttempts--;
124+
this.attempts++;
125+
126+
this._req = Request.request(this.options, function (err, response, body) {
127+
if (response) {
128+
response.attempts = this.attempts;
129+
}
130+
if (this.retryStrategy(err, response, body) && this.maxAttempts > 0) {
131+
this._timeout = setTimeout(this._tryUntilFail.bind(this), this.delayStrategy.call(this, err, response, body));
132+
return;
133+
}
134+
135+
this.reply(err, response, body);
136+
}.bind(this));
135137
};
136138

137139
Request.prototype.abort = function () {
138-
if (this._req) {
139-
this._req.abort();
140-
}
141-
clearTimeout(this._timeout);
142-
this.reply(new Error('Aborted'));
140+
if (this._req) {
141+
this._req.abort();
142+
}
143+
clearTimeout(this._timeout);
144+
this.reply(new Error('Aborted'));
143145
};
144146

145147
// expose request methods from RequestRetry
146-
['end', 'on', 'emit', 'once', 'setMaxListeners', 'start', 'removeListener', 'pipe', 'write'].forEach(function (requestMethod) {
147-
Request.prototype[requestMethod] = function exposedRequestMethod () {
148-
return this._req[requestMethod].apply(this._req, arguments);
149-
};
148+
['end', 'on', 'emit', 'once', 'setMaxListeners', 'start', 'removeListener', 'pipe', 'write', 'auth', ].forEach(function (requestMethod) {
149+
Request.prototype[requestMethod] = function exposedRequestMethod() {
150+
return this._req[requestMethod].apply(this._req, arguments);
151+
};
150152
});
151153

152154
// expose promise methods
153155
['then', 'catch', 'finally', 'fail', 'done'].forEach(function (promiseMethod) {
154-
Request.prototype[promiseMethod] = function exposedPromiseMethod () {
155-
if (this._callback) {
156-
throw new Error('A callback was provided but waiting a promise, use only one pattern');
157-
}
158-
return this._promise[promiseMethod].apply(this._promise, arguments);
159-
};
156+
Request.prototype[promiseMethod] = function exposedPromiseMethod() {
157+
if (this._callback) {
158+
throw new Error('A callback was provided but waiting a promise, use only one pattern');
159+
}
160+
return this._promise[promiseMethod].apply(this._promise, arguments);
161+
};
160162
});
161163

162164
function Factory(url, options, f) {
163-
var retryConfig = _.chain(_.isObject(url) ? url : options || {}).defaults(DEFAULTS).pick(Object.keys(DEFAULTS)).value();
164-
var req = new Request(url, options, f, retryConfig);
165-
req._tryUntilFail();
166-
return req;
165+
var retryConfig = _.chain(_.isObject(url) ? url : options || {}).defaults(DEFAULTS).pick(Object.keys(DEFAULTS)).value();
166+
var req = new Request(url, options, f, retryConfig);
167+
req._tryUntilFail();
168+
return req;
167169
}
168170

169171
// adds a helper for HTTP method `verb` to object `obj`
170172
function makeHelper(obj, verb) {
171-
obj[verb] = function helper(url, options, f) {
172-
// ('url')
173-
if(_.isString(url)){
174-
// ('url', f)
175-
if(_.isFunction(options)){
176-
f = options;
177-
}
178-
179-
if(!_.isObject(options)){
180-
options = {};
181-
}
182-
183-
// ('url', {object})
184-
options.url = url;
185-
}
186-
187-
if(_.isObject(url)){
188-
if(_.isFunction(options)){
189-
f = options;
190-
}
191-
options = url;
192-
}
193-
194-
options.method = verb.toUpperCase();
195-
return obj(options, f);
196-
};
173+
obj[verb] = function helper(url, options, f) {
174+
// ('url')
175+
if (_.isString(url)) {
176+
// ('url', f)
177+
if (_.isFunction(options)) {
178+
f = options;
179+
}
180+
181+
if (!_.isObject(options)) {
182+
options = {};
183+
}
184+
185+
// ('url', {object})
186+
options.url = url;
187+
}
188+
189+
if (_.isObject(url)) {
190+
if (_.isFunction(options)) {
191+
f = options;
192+
}
193+
options = url;
194+
}
195+
196+
options.method = verb.toUpperCase();
197+
return obj(options, f);
198+
};
197199
}
198200

199201
function defaults(defaultOptions, defaultF) {
200-
var factory = function (options, f) {
201-
if (typeof options === "string") {
202-
options = { uri: options };
203-
}
204-
return Factory.apply(null, [ extend(true, {}, defaultOptions, options), f || defaultF ]);
205-
};
206-
207-
factory.defaults = function (newDefaultOptions, newDefaultF) {
208-
return defaults.apply(null, [ extend(true, {}, defaultOptions, newDefaultOptions), newDefaultF || defaultF ]);
209-
};
210-
211-
factory.Request = Request;
212-
factory.RetryStrategies = RetryStrategies;
202+
var factory = function (options, f) {
203+
if (typeof options === "string") {
204+
options = {
205+
uri: options
206+
};
207+
}
208+
return Factory.apply(null, [extend(true, {}, defaultOptions, options), f || defaultF]);
209+
};
210+
211+
factory.defaults = function (newDefaultOptions, newDefaultF) {
212+
return defaults.apply(null, [extend(true, {}, defaultOptions, newDefaultOptions), newDefaultF || defaultF]);
213+
};
214+
215+
factory.Request = Request;
216+
factory.RetryStrategies = RetryStrategies;
213217

214218
['get', 'head', 'post', 'put', 'patch', 'delete'].forEach(function (verb) {
215-
makeHelper(factory, verb);
216-
});
217-
factory.del = factory['delete'];
219+
makeHelper(factory, verb);
220+
});
221+
factory.del = factory['delete'];
218222

219-
return factory;
223+
return factory;
220224
}
221225

222226
module.exports = Factory;
@@ -227,6 +231,10 @@ Factory.RetryStrategies = RetryStrategies;
227231

228232
// define .get/.post/... helpers
229233
['get', 'head', 'post', 'put', 'patch', 'delete'].forEach(function (verb) {
230-
makeHelper(Factory, verb);
234+
makeHelper(Factory, verb);
231235
});
232236
Factory.del = Factory['delete'];
237+
238+
['jar','cookie'].forEach(function (method) {
239+
Factory[method] = Factory.Request.request[method];
240+
});

0 commit comments

Comments
 (0)