proxy-rotator-js 1.0.8 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/README.md +23 -0
  2. package/package.json +1 -1
  3. package/src/ProxyRotator.js +7 -1
  4. package/test/options.js +32 -0
  5. package/test_proxies/node_modules/.package-lock.json +98 -0
  6. package/test_proxies/node_modules/asynckit/LICENSE +21 -0
  7. package/test_proxies/node_modules/asynckit/README.md +233 -0
  8. package/test_proxies/node_modules/asynckit/bench.js +76 -0
  9. package/test_proxies/node_modules/asynckit/index.js +6 -0
  10. package/test_proxies/node_modules/asynckit/lib/abort.js +29 -0
  11. package/test_proxies/node_modules/asynckit/lib/async.js +34 -0
  12. package/test_proxies/node_modules/asynckit/lib/defer.js +26 -0
  13. package/test_proxies/node_modules/asynckit/lib/iterate.js +75 -0
  14. package/test_proxies/node_modules/asynckit/lib/readable_asynckit.js +91 -0
  15. package/test_proxies/node_modules/asynckit/lib/readable_parallel.js +25 -0
  16. package/test_proxies/node_modules/asynckit/lib/readable_serial.js +25 -0
  17. package/test_proxies/node_modules/asynckit/lib/readable_serial_ordered.js +29 -0
  18. package/test_proxies/node_modules/asynckit/lib/state.js +37 -0
  19. package/test_proxies/node_modules/asynckit/lib/streamify.js +141 -0
  20. package/test_proxies/node_modules/asynckit/lib/terminator.js +29 -0
  21. package/test_proxies/node_modules/asynckit/package.json +63 -0
  22. package/test_proxies/node_modules/asynckit/parallel.js +43 -0
  23. package/test_proxies/node_modules/asynckit/serial.js +17 -0
  24. package/test_proxies/node_modules/asynckit/serialOrdered.js +75 -0
  25. package/test_proxies/node_modules/asynckit/stream.js +21 -0
  26. package/test_proxies/node_modules/axios/CHANGELOG.md +790 -0
  27. package/test_proxies/node_modules/axios/LICENSE +7 -0
  28. package/test_proxies/node_modules/axios/MIGRATION_GUIDE.md +3 -0
  29. package/test_proxies/node_modules/axios/README.md +1605 -0
  30. package/test_proxies/node_modules/axios/SECURITY.md +6 -0
  31. package/test_proxies/node_modules/axios/dist/axios.js +3061 -0
  32. package/test_proxies/node_modules/axios/dist/axios.js.map +1 -0
  33. package/test_proxies/node_modules/axios/dist/axios.min.js +2 -0
  34. package/test_proxies/node_modules/axios/dist/axios.min.js.map +1 -0
  35. package/test_proxies/node_modules/axios/dist/browser/axios.cjs +3234 -0
  36. package/test_proxies/node_modules/axios/dist/browser/axios.cjs.map +1 -0
  37. package/test_proxies/node_modules/axios/dist/esm/axios.js +3257 -0
  38. package/test_proxies/node_modules/axios/dist/esm/axios.js.map +1 -0
  39. package/test_proxies/node_modules/axios/dist/esm/axios.min.js +2 -0
  40. package/test_proxies/node_modules/axios/dist/esm/axios.min.js.map +1 -0
  41. package/test_proxies/node_modules/axios/dist/node/axios.cjs +4327 -0
  42. package/test_proxies/node_modules/axios/dist/node/axios.cjs.map +1 -0
  43. package/test_proxies/node_modules/axios/index.d.cts +542 -0
  44. package/test_proxies/node_modules/axios/index.d.ts +559 -0
  45. package/test_proxies/node_modules/axios/index.js +43 -0
  46. package/test_proxies/node_modules/axios/lib/adapters/README.md +37 -0
  47. package/test_proxies/node_modules/axios/lib/adapters/adapters.js +77 -0
  48. package/test_proxies/node_modules/axios/lib/adapters/http.js +681 -0
  49. package/test_proxies/node_modules/axios/lib/adapters/xhr.js +260 -0
  50. package/test_proxies/node_modules/axios/lib/axios.js +89 -0
  51. package/test_proxies/node_modules/axios/lib/cancel/CancelToken.js +121 -0
  52. package/test_proxies/node_modules/axios/lib/cancel/CanceledError.js +25 -0
  53. package/test_proxies/node_modules/axios/lib/cancel/isCancel.js +5 -0
  54. package/test_proxies/node_modules/axios/lib/core/Axios.js +201 -0
  55. package/test_proxies/node_modules/axios/lib/core/AxiosError.js +100 -0
  56. package/test_proxies/node_modules/axios/lib/core/AxiosHeaders.js +298 -0
  57. package/test_proxies/node_modules/axios/lib/core/InterceptorManager.js +71 -0
  58. package/test_proxies/node_modules/axios/lib/core/README.md +8 -0
  59. package/test_proxies/node_modules/axios/lib/core/buildFullPath.js +21 -0
  60. package/test_proxies/node_modules/axios/lib/core/dispatchRequest.js +81 -0
  61. package/test_proxies/node_modules/axios/lib/core/mergeConfig.js +106 -0
  62. package/test_proxies/node_modules/axios/lib/core/settle.js +27 -0
  63. package/test_proxies/node_modules/axios/lib/core/transformData.js +28 -0
  64. package/test_proxies/node_modules/axios/lib/defaults/index.js +159 -0
  65. package/test_proxies/node_modules/axios/lib/defaults/transitional.js +7 -0
  66. package/test_proxies/node_modules/axios/lib/env/README.md +3 -0
  67. package/test_proxies/node_modules/axios/lib/env/classes/FormData.js +2 -0
  68. package/test_proxies/node_modules/axios/lib/env/data.js +1 -0
  69. package/test_proxies/node_modules/axios/lib/helpers/AxiosTransformStream.js +191 -0
  70. package/test_proxies/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +58 -0
  71. package/test_proxies/node_modules/axios/lib/helpers/HttpStatusCode.js +71 -0
  72. package/test_proxies/node_modules/axios/lib/helpers/README.md +7 -0
  73. package/test_proxies/node_modules/axios/lib/helpers/ZlibHeaderTransformStream.js +28 -0
  74. package/test_proxies/node_modules/axios/lib/helpers/bind.js +7 -0
  75. package/test_proxies/node_modules/axios/lib/helpers/buildURL.js +63 -0
  76. package/test_proxies/node_modules/axios/lib/helpers/callbackify.js +16 -0
  77. package/test_proxies/node_modules/axios/lib/helpers/combineURLs.js +15 -0
  78. package/test_proxies/node_modules/axios/lib/helpers/cookies.js +42 -0
  79. package/test_proxies/node_modules/axios/lib/helpers/deprecatedMethod.js +26 -0
  80. package/test_proxies/node_modules/axios/lib/helpers/formDataToJSON.js +92 -0
  81. package/test_proxies/node_modules/axios/lib/helpers/formDataToStream.js +111 -0
  82. package/test_proxies/node_modules/axios/lib/helpers/fromDataURI.js +53 -0
  83. package/test_proxies/node_modules/axios/lib/helpers/isAbsoluteURL.js +15 -0
  84. package/test_proxies/node_modules/axios/lib/helpers/isAxiosError.js +14 -0
  85. package/test_proxies/node_modules/axios/lib/helpers/isURLSameOrigin.js +67 -0
  86. package/test_proxies/node_modules/axios/lib/helpers/null.js +2 -0
  87. package/test_proxies/node_modules/axios/lib/helpers/parseHeaders.js +55 -0
  88. package/test_proxies/node_modules/axios/lib/helpers/parseProtocol.js +6 -0
  89. package/test_proxies/node_modules/axios/lib/helpers/readBlob.js +15 -0
  90. package/test_proxies/node_modules/axios/lib/helpers/speedometer.js +55 -0
  91. package/test_proxies/node_modules/axios/lib/helpers/spread.js +28 -0
  92. package/test_proxies/node_modules/axios/lib/helpers/throttle.js +33 -0
  93. package/test_proxies/node_modules/axios/lib/helpers/toFormData.js +219 -0
  94. package/test_proxies/node_modules/axios/lib/helpers/toURLEncodedForm.js +18 -0
  95. package/test_proxies/node_modules/axios/lib/helpers/validator.js +91 -0
  96. package/test_proxies/node_modules/axios/lib/platform/browser/classes/Blob.js +3 -0
  97. package/test_proxies/node_modules/axios/lib/platform/browser/classes/FormData.js +3 -0
  98. package/test_proxies/node_modules/axios/lib/platform/browser/classes/URLSearchParams.js +4 -0
  99. package/test_proxies/node_modules/axios/lib/platform/browser/index.js +13 -0
  100. package/test_proxies/node_modules/axios/lib/platform/common/utils.js +47 -0
  101. package/test_proxies/node_modules/axios/lib/platform/index.js +7 -0
  102. package/test_proxies/node_modules/axios/lib/platform/node/classes/FormData.js +3 -0
  103. package/test_proxies/node_modules/axios/lib/platform/node/classes/URLSearchParams.js +4 -0
  104. package/test_proxies/node_modules/axios/lib/platform/node/index.js +12 -0
  105. package/test_proxies/node_modules/axios/lib/utils.js +723 -0
  106. package/test_proxies/node_modules/axios/package.json +218 -0
  107. package/test_proxies/node_modules/combined-stream/License +19 -0
  108. package/test_proxies/node_modules/combined-stream/Readme.md +138 -0
  109. package/test_proxies/node_modules/combined-stream/lib/combined_stream.js +208 -0
  110. package/test_proxies/node_modules/combined-stream/package.json +25 -0
  111. package/test_proxies/node_modules/combined-stream/yarn.lock +17 -0
  112. package/test_proxies/node_modules/delayed-stream/License +19 -0
  113. package/test_proxies/node_modules/delayed-stream/Makefile +7 -0
  114. package/test_proxies/node_modules/delayed-stream/Readme.md +141 -0
  115. package/test_proxies/node_modules/delayed-stream/lib/delayed_stream.js +107 -0
  116. package/test_proxies/node_modules/delayed-stream/package.json +27 -0
  117. package/test_proxies/node_modules/follow-redirects/LICENSE +18 -0
  118. package/test_proxies/node_modules/follow-redirects/README.md +155 -0
  119. package/test_proxies/node_modules/follow-redirects/debug.js +15 -0
  120. package/test_proxies/node_modules/follow-redirects/http.js +1 -0
  121. package/test_proxies/node_modules/follow-redirects/https.js +1 -0
  122. package/test_proxies/node_modules/follow-redirects/index.js +633 -0
  123. package/test_proxies/node_modules/follow-redirects/package.json +58 -0
  124. package/test_proxies/node_modules/form-data/License +19 -0
  125. package/test_proxies/node_modules/form-data/README.md.bak +358 -0
  126. package/test_proxies/node_modules/form-data/Readme.md +358 -0
  127. package/test_proxies/node_modules/form-data/index.d.ts +62 -0
  128. package/test_proxies/node_modules/form-data/lib/browser.js +2 -0
  129. package/test_proxies/node_modules/form-data/lib/form_data.js +501 -0
  130. package/test_proxies/node_modules/form-data/lib/populate.js +10 -0
  131. package/test_proxies/node_modules/form-data/package.json +68 -0
  132. package/test_proxies/node_modules/mime-db/HISTORY.md +507 -0
  133. package/test_proxies/node_modules/mime-db/LICENSE +23 -0
  134. package/test_proxies/node_modules/mime-db/README.md +100 -0
  135. package/test_proxies/node_modules/mime-db/db.json +8519 -0
  136. package/test_proxies/node_modules/mime-db/index.js +12 -0
  137. package/test_proxies/node_modules/mime-db/package.json +60 -0
  138. package/test_proxies/node_modules/mime-types/HISTORY.md +397 -0
  139. package/test_proxies/node_modules/mime-types/LICENSE +23 -0
  140. package/test_proxies/node_modules/mime-types/README.md +113 -0
  141. package/test_proxies/node_modules/mime-types/index.js +188 -0
  142. package/test_proxies/node_modules/mime-types/package.json +44 -0
  143. package/test_proxies/node_modules/proxy-from-env/.eslintrc +29 -0
  144. package/test_proxies/node_modules/proxy-from-env/.travis.yml +10 -0
  145. package/test_proxies/node_modules/proxy-from-env/LICENSE +20 -0
  146. package/test_proxies/node_modules/proxy-from-env/README.md +131 -0
  147. package/test_proxies/node_modules/proxy-from-env/index.js +108 -0
  148. package/test_proxies/node_modules/proxy-from-env/package.json +34 -0
  149. package/test_proxies/node_modules/proxy-from-env/test.js +483 -0
  150. package/test_proxies/package-lock.json +106 -0
  151. package/test_proxies/package.json +14 -0
  152. package/test_proxies/proxies.txt +7000 -0
  153. package/test_proxies/test_proxies.js +62 -0
@@ -0,0 +1,633 @@
1
+ var url = require("url");
2
+ var URL = url.URL;
3
+ var http = require("http");
4
+ var https = require("https");
5
+ var Writable = require("stream").Writable;
6
+ var assert = require("assert");
7
+ var debug = require("./debug");
8
+
9
+ // Create handlers that pass events from native requests
10
+ var events = ["abort", "aborted", "connect", "error", "socket", "timeout"];
11
+ var eventHandlers = Object.create(null);
12
+ events.forEach(function (event) {
13
+ eventHandlers[event] = function (arg1, arg2, arg3) {
14
+ this._redirectable.emit(event, arg1, arg2, arg3);
15
+ };
16
+ });
17
+
18
+ var InvalidUrlError = createErrorType(
19
+ "ERR_INVALID_URL",
20
+ "Invalid URL",
21
+ TypeError
22
+ );
23
+ // Error types with codes
24
+ var RedirectionError = createErrorType(
25
+ "ERR_FR_REDIRECTION_FAILURE",
26
+ "Redirected request failed"
27
+ );
28
+ var TooManyRedirectsError = createErrorType(
29
+ "ERR_FR_TOO_MANY_REDIRECTS",
30
+ "Maximum number of redirects exceeded"
31
+ );
32
+ var MaxBodyLengthExceededError = createErrorType(
33
+ "ERR_FR_MAX_BODY_LENGTH_EXCEEDED",
34
+ "Request body larger than maxBodyLength limit"
35
+ );
36
+ var WriteAfterEndError = createErrorType(
37
+ "ERR_STREAM_WRITE_AFTER_END",
38
+ "write after end"
39
+ );
40
+
41
+ // istanbul ignore next
42
+ var destroy = Writable.prototype.destroy || noop;
43
+
44
+ // An HTTP(S) request that can be redirected
45
+ function RedirectableRequest(options, responseCallback) {
46
+ // Initialize the request
47
+ Writable.call(this);
48
+ this._sanitizeOptions(options);
49
+ this._options = options;
50
+ this._ended = false;
51
+ this._ending = false;
52
+ this._redirectCount = 0;
53
+ this._redirects = [];
54
+ this._requestBodyLength = 0;
55
+ this._requestBodyBuffers = [];
56
+
57
+ // Attach a callback if passed
58
+ if (responseCallback) {
59
+ this.on("response", responseCallback);
60
+ }
61
+
62
+ // React to responses of native requests
63
+ var self = this;
64
+ this._onNativeResponse = function (response) {
65
+ self._processResponse(response);
66
+ };
67
+
68
+ // Perform the first request
69
+ this._performRequest();
70
+ }
71
+ RedirectableRequest.prototype = Object.create(Writable.prototype);
72
+
73
+ RedirectableRequest.prototype.abort = function () {
74
+ destroyRequest(this._currentRequest);
75
+ this._currentRequest.abort();
76
+ this.emit("abort");
77
+ };
78
+
79
+ RedirectableRequest.prototype.destroy = function (error) {
80
+ destroyRequest(this._currentRequest, error);
81
+ destroy.call(this, error);
82
+ return this;
83
+ };
84
+
85
+ // Writes buffered data to the current native request
86
+ RedirectableRequest.prototype.write = function (data, encoding, callback) {
87
+ // Writing is not allowed if end has been called
88
+ if (this._ending) {
89
+ throw new WriteAfterEndError();
90
+ }
91
+
92
+ // Validate input and shift parameters if necessary
93
+ if (!isString(data) && !isBuffer(data)) {
94
+ throw new TypeError("data should be a string, Buffer or Uint8Array");
95
+ }
96
+ if (isFunction(encoding)) {
97
+ callback = encoding;
98
+ encoding = null;
99
+ }
100
+
101
+ // Ignore empty buffers, since writing them doesn't invoke the callback
102
+ // https://github.com/nodejs/node/issues/22066
103
+ if (data.length === 0) {
104
+ if (callback) {
105
+ callback();
106
+ }
107
+ return;
108
+ }
109
+ // Only write when we don't exceed the maximum body length
110
+ if (this._requestBodyLength + data.length <= this._options.maxBodyLength) {
111
+ this._requestBodyLength += data.length;
112
+ this._requestBodyBuffers.push({ data: data, encoding: encoding });
113
+ this._currentRequest.write(data, encoding, callback);
114
+ }
115
+ // Error when we exceed the maximum body length
116
+ else {
117
+ this.emit("error", new MaxBodyLengthExceededError());
118
+ this.abort();
119
+ }
120
+ };
121
+
122
+ // Ends the current native request
123
+ RedirectableRequest.prototype.end = function (data, encoding, callback) {
124
+ // Shift parameters if necessary
125
+ if (isFunction(data)) {
126
+ callback = data;
127
+ data = encoding = null;
128
+ }
129
+ else if (isFunction(encoding)) {
130
+ callback = encoding;
131
+ encoding = null;
132
+ }
133
+
134
+ // Write data if needed and end
135
+ if (!data) {
136
+ this._ended = this._ending = true;
137
+ this._currentRequest.end(null, null, callback);
138
+ }
139
+ else {
140
+ var self = this;
141
+ var currentRequest = this._currentRequest;
142
+ this.write(data, encoding, function () {
143
+ self._ended = true;
144
+ currentRequest.end(null, null, callback);
145
+ });
146
+ this._ending = true;
147
+ }
148
+ };
149
+
150
+ // Sets a header value on the current native request
151
+ RedirectableRequest.prototype.setHeader = function (name, value) {
152
+ this._options.headers[name] = value;
153
+ this._currentRequest.setHeader(name, value);
154
+ };
155
+
156
+ // Clears a header value on the current native request
157
+ RedirectableRequest.prototype.removeHeader = function (name) {
158
+ delete this._options.headers[name];
159
+ this._currentRequest.removeHeader(name);
160
+ };
161
+
162
+ // Global timeout for all underlying requests
163
+ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
164
+ var self = this;
165
+
166
+ // Destroys the socket on timeout
167
+ function destroyOnTimeout(socket) {
168
+ socket.setTimeout(msecs);
169
+ socket.removeListener("timeout", socket.destroy);
170
+ socket.addListener("timeout", socket.destroy);
171
+ }
172
+
173
+ // Sets up a timer to trigger a timeout event
174
+ function startTimer(socket) {
175
+ if (self._timeout) {
176
+ clearTimeout(self._timeout);
177
+ }
178
+ self._timeout = setTimeout(function () {
179
+ self.emit("timeout");
180
+ clearTimer();
181
+ }, msecs);
182
+ destroyOnTimeout(socket);
183
+ }
184
+
185
+ // Stops a timeout from triggering
186
+ function clearTimer() {
187
+ // Clear the timeout
188
+ if (self._timeout) {
189
+ clearTimeout(self._timeout);
190
+ self._timeout = null;
191
+ }
192
+
193
+ // Clean up all attached listeners
194
+ self.removeListener("abort", clearTimer);
195
+ self.removeListener("error", clearTimer);
196
+ self.removeListener("response", clearTimer);
197
+ self.removeListener("close", clearTimer);
198
+ if (callback) {
199
+ self.removeListener("timeout", callback);
200
+ }
201
+ if (!self.socket) {
202
+ self._currentRequest.removeListener("socket", startTimer);
203
+ }
204
+ }
205
+
206
+ // Attach callback if passed
207
+ if (callback) {
208
+ this.on("timeout", callback);
209
+ }
210
+
211
+ // Start the timer if or when the socket is opened
212
+ if (this.socket) {
213
+ startTimer(this.socket);
214
+ }
215
+ else {
216
+ this._currentRequest.once("socket", startTimer);
217
+ }
218
+
219
+ // Clean up on events
220
+ this.on("socket", destroyOnTimeout);
221
+ this.on("abort", clearTimer);
222
+ this.on("error", clearTimer);
223
+ this.on("response", clearTimer);
224
+ this.on("close", clearTimer);
225
+
226
+ return this;
227
+ };
228
+
229
+ // Proxy all other public ClientRequest methods
230
+ [
231
+ "flushHeaders", "getHeader",
232
+ "setNoDelay", "setSocketKeepAlive",
233
+ ].forEach(function (method) {
234
+ RedirectableRequest.prototype[method] = function (a, b) {
235
+ return this._currentRequest[method](a, b);
236
+ };
237
+ });
238
+
239
+ // Proxy all public ClientRequest properties
240
+ ["aborted", "connection", "socket"].forEach(function (property) {
241
+ Object.defineProperty(RedirectableRequest.prototype, property, {
242
+ get: function () { return this._currentRequest[property]; },
243
+ });
244
+ });
245
+
246
+ RedirectableRequest.prototype._sanitizeOptions = function (options) {
247
+ // Ensure headers are always present
248
+ if (!options.headers) {
249
+ options.headers = {};
250
+ }
251
+
252
+ // Since http.request treats host as an alias of hostname,
253
+ // but the url module interprets host as hostname plus port,
254
+ // eliminate the host property to avoid confusion.
255
+ if (options.host) {
256
+ // Use hostname if set, because it has precedence
257
+ if (!options.hostname) {
258
+ options.hostname = options.host;
259
+ }
260
+ delete options.host;
261
+ }
262
+
263
+ // Complete the URL object when necessary
264
+ if (!options.pathname && options.path) {
265
+ var searchPos = options.path.indexOf("?");
266
+ if (searchPos < 0) {
267
+ options.pathname = options.path;
268
+ }
269
+ else {
270
+ options.pathname = options.path.substring(0, searchPos);
271
+ options.search = options.path.substring(searchPos);
272
+ }
273
+ }
274
+ };
275
+
276
+
277
+ // Executes the next native request (initial or redirect)
278
+ RedirectableRequest.prototype._performRequest = function () {
279
+ // Load the native protocol
280
+ var protocol = this._options.protocol;
281
+ var nativeProtocol = this._options.nativeProtocols[protocol];
282
+ if (!nativeProtocol) {
283
+ this.emit("error", new TypeError("Unsupported protocol " + protocol));
284
+ return;
285
+ }
286
+
287
+ // If specified, use the agent corresponding to the protocol
288
+ // (HTTP and HTTPS use different types of agents)
289
+ if (this._options.agents) {
290
+ var scheme = protocol.slice(0, -1);
291
+ this._options.agent = this._options.agents[scheme];
292
+ }
293
+
294
+ // Create the native request and set up its event handlers
295
+ var request = this._currentRequest =
296
+ nativeProtocol.request(this._options, this._onNativeResponse);
297
+ request._redirectable = this;
298
+ for (var event of events) {
299
+ request.on(event, eventHandlers[event]);
300
+ }
301
+
302
+ // RFC7230§5.3.1: When making a request directly to an origin server, […]
303
+ // a client MUST send only the absolute path […] as the request-target.
304
+ this._currentUrl = /^\//.test(this._options.path) ?
305
+ url.format(this._options) :
306
+ // When making a request to a proxy, […]
307
+ // a client MUST send the target URI in absolute-form […].
308
+ this._options.path;
309
+
310
+ // End a redirected request
311
+ // (The first request must be ended explicitly with RedirectableRequest#end)
312
+ if (this._isRedirect) {
313
+ // Write the request entity and end
314
+ var i = 0;
315
+ var self = this;
316
+ var buffers = this._requestBodyBuffers;
317
+ (function writeNext(error) {
318
+ // Only write if this request has not been redirected yet
319
+ /* istanbul ignore else */
320
+ if (request === self._currentRequest) {
321
+ // Report any write errors
322
+ /* istanbul ignore if */
323
+ if (error) {
324
+ self.emit("error", error);
325
+ }
326
+ // Write the next buffer if there are still left
327
+ else if (i < buffers.length) {
328
+ var buffer = buffers[i++];
329
+ /* istanbul ignore else */
330
+ if (!request.finished) {
331
+ request.write(buffer.data, buffer.encoding, writeNext);
332
+ }
333
+ }
334
+ // End the request if `end` has been called on us
335
+ else if (self._ended) {
336
+ request.end();
337
+ }
338
+ }
339
+ }());
340
+ }
341
+ };
342
+
343
+ // Processes a response from the current native request
344
+ RedirectableRequest.prototype._processResponse = function (response) {
345
+ // Store the redirected response
346
+ var statusCode = response.statusCode;
347
+ if (this._options.trackRedirects) {
348
+ this._redirects.push({
349
+ url: this._currentUrl,
350
+ headers: response.headers,
351
+ statusCode: statusCode,
352
+ });
353
+ }
354
+
355
+ // RFC7231§6.4: The 3xx (Redirection) class of status code indicates
356
+ // that further action needs to be taken by the user agent in order to
357
+ // fulfill the request. If a Location header field is provided,
358
+ // the user agent MAY automatically redirect its request to the URI
359
+ // referenced by the Location field value,
360
+ // even if the specific status code is not understood.
361
+
362
+ // If the response is not a redirect; return it as-is
363
+ var location = response.headers.location;
364
+ if (!location || this._options.followRedirects === false ||
365
+ statusCode < 300 || statusCode >= 400) {
366
+ response.responseUrl = this._currentUrl;
367
+ response.redirects = this._redirects;
368
+ this.emit("response", response);
369
+
370
+ // Clean up
371
+ this._requestBodyBuffers = [];
372
+ return;
373
+ }
374
+
375
+ // The response is a redirect, so abort the current request
376
+ destroyRequest(this._currentRequest);
377
+ // Discard the remainder of the response to avoid waiting for data
378
+ response.destroy();
379
+
380
+ // RFC7231§6.4: A client SHOULD detect and intervene
381
+ // in cyclical redirections (i.e., "infinite" redirection loops).
382
+ if (++this._redirectCount > this._options.maxRedirects) {
383
+ this.emit("error", new TooManyRedirectsError());
384
+ return;
385
+ }
386
+
387
+ // Store the request headers if applicable
388
+ var requestHeaders;
389
+ var beforeRedirect = this._options.beforeRedirect;
390
+ if (beforeRedirect) {
391
+ requestHeaders = Object.assign({
392
+ // The Host header was set by nativeProtocol.request
393
+ Host: response.req.getHeader("host"),
394
+ }, this._options.headers);
395
+ }
396
+
397
+ // RFC7231§6.4: Automatic redirection needs to done with
398
+ // care for methods not known to be safe, […]
399
+ // RFC7231§6.4.2–3: For historical reasons, a user agent MAY change
400
+ // the request method from POST to GET for the subsequent request.
401
+ var method = this._options.method;
402
+ if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" ||
403
+ // RFC7231§6.4.4: The 303 (See Other) status code indicates that
404
+ // the server is redirecting the user agent to a different resource […]
405
+ // A user agent can perform a retrieval request targeting that URI
406
+ // (a GET or HEAD request if using HTTP) […]
407
+ (statusCode === 303) && !/^(?:GET|HEAD)$/.test(this._options.method)) {
408
+ this._options.method = "GET";
409
+ // Drop a possible entity and headers related to it
410
+ this._requestBodyBuffers = [];
411
+ removeMatchingHeaders(/^content-/i, this._options.headers);
412
+ }
413
+
414
+ // Drop the Host header, as the redirect might lead to a different host
415
+ var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
416
+
417
+ // If the redirect is relative, carry over the host of the last request
418
+ var currentUrlParts = url.parse(this._currentUrl);
419
+ var currentHost = currentHostHeader || currentUrlParts.host;
420
+ var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
421
+ url.format(Object.assign(currentUrlParts, { host: currentHost }));
422
+
423
+ // Determine the URL of the redirection
424
+ var redirectUrl;
425
+ try {
426
+ redirectUrl = url.resolve(currentUrl, location);
427
+ }
428
+ catch (cause) {
429
+ this.emit("error", new RedirectionError({ cause: cause }));
430
+ return;
431
+ }
432
+
433
+ // Create the redirected request
434
+ debug("redirecting to", redirectUrl);
435
+ this._isRedirect = true;
436
+ var redirectUrlParts = url.parse(redirectUrl);
437
+ Object.assign(this._options, redirectUrlParts);
438
+
439
+ // Drop confidential headers when redirecting to a less secure protocol
440
+ // or to a different domain that is not a superdomain
441
+ if (redirectUrlParts.protocol !== currentUrlParts.protocol &&
442
+ redirectUrlParts.protocol !== "https:" ||
443
+ redirectUrlParts.host !== currentHost &&
444
+ !isSubdomain(redirectUrlParts.host, currentHost)) {
445
+ removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
446
+ }
447
+
448
+ // Evaluate the beforeRedirect callback
449
+ if (isFunction(beforeRedirect)) {
450
+ var responseDetails = {
451
+ headers: response.headers,
452
+ statusCode: statusCode,
453
+ };
454
+ var requestDetails = {
455
+ url: currentUrl,
456
+ method: method,
457
+ headers: requestHeaders,
458
+ };
459
+ try {
460
+ beforeRedirect(this._options, responseDetails, requestDetails);
461
+ }
462
+ catch (err) {
463
+ this.emit("error", err);
464
+ return;
465
+ }
466
+ this._sanitizeOptions(this._options);
467
+ }
468
+
469
+ // Perform the redirected request
470
+ try {
471
+ this._performRequest();
472
+ }
473
+ catch (cause) {
474
+ this.emit("error", new RedirectionError({ cause: cause }));
475
+ }
476
+ };
477
+
478
+ // Wraps the key/value object of protocols with redirect functionality
479
+ function wrap(protocols) {
480
+ // Default settings
481
+ var exports = {
482
+ maxRedirects: 21,
483
+ maxBodyLength: 10 * 1024 * 1024,
484
+ };
485
+
486
+ // Wrap each protocol
487
+ var nativeProtocols = {};
488
+ Object.keys(protocols).forEach(function (scheme) {
489
+ var protocol = scheme + ":";
490
+ var nativeProtocol = nativeProtocols[protocol] = protocols[scheme];
491
+ var wrappedProtocol = exports[scheme] = Object.create(nativeProtocol);
492
+
493
+ // Executes a request, following redirects
494
+ function request(input, options, callback) {
495
+ // Parse parameters
496
+ if (isString(input)) {
497
+ var parsed;
498
+ try {
499
+ parsed = urlToOptions(new URL(input));
500
+ }
501
+ catch (err) {
502
+ /* istanbul ignore next */
503
+ parsed = url.parse(input);
504
+ }
505
+ if (!isString(parsed.protocol)) {
506
+ throw new InvalidUrlError({ input });
507
+ }
508
+ input = parsed;
509
+ }
510
+ else if (URL && (input instanceof URL)) {
511
+ input = urlToOptions(input);
512
+ }
513
+ else {
514
+ callback = options;
515
+ options = input;
516
+ input = { protocol: protocol };
517
+ }
518
+ if (isFunction(options)) {
519
+ callback = options;
520
+ options = null;
521
+ }
522
+
523
+ // Set defaults
524
+ options = Object.assign({
525
+ maxRedirects: exports.maxRedirects,
526
+ maxBodyLength: exports.maxBodyLength,
527
+ }, input, options);
528
+ options.nativeProtocols = nativeProtocols;
529
+ if (!isString(options.host) && !isString(options.hostname)) {
530
+ options.hostname = "::1";
531
+ }
532
+
533
+ assert.equal(options.protocol, protocol, "protocol mismatch");
534
+ debug("options", options);
535
+ return new RedirectableRequest(options, callback);
536
+ }
537
+
538
+ // Executes a GET request, following redirects
539
+ function get(input, options, callback) {
540
+ var wrappedRequest = wrappedProtocol.request(input, options, callback);
541
+ wrappedRequest.end();
542
+ return wrappedRequest;
543
+ }
544
+
545
+ // Expose the properties on the wrapped protocol
546
+ Object.defineProperties(wrappedProtocol, {
547
+ request: { value: request, configurable: true, enumerable: true, writable: true },
548
+ get: { value: get, configurable: true, enumerable: true, writable: true },
549
+ });
550
+ });
551
+ return exports;
552
+ }
553
+
554
+ /* istanbul ignore next */
555
+ function noop() { /* empty */ }
556
+
557
+ // from https://github.com/nodejs/node/blob/master/lib/internal/url.js
558
+ function urlToOptions(urlObject) {
559
+ var options = {
560
+ protocol: urlObject.protocol,
561
+ hostname: urlObject.hostname.startsWith("[") ?
562
+ /* istanbul ignore next */
563
+ urlObject.hostname.slice(1, -1) :
564
+ urlObject.hostname,
565
+ hash: urlObject.hash,
566
+ search: urlObject.search,
567
+ pathname: urlObject.pathname,
568
+ path: urlObject.pathname + urlObject.search,
569
+ href: urlObject.href,
570
+ };
571
+ if (urlObject.port !== "") {
572
+ options.port = Number(urlObject.port);
573
+ }
574
+ return options;
575
+ }
576
+
577
+ function removeMatchingHeaders(regex, headers) {
578
+ var lastValue;
579
+ for (var header in headers) {
580
+ if (regex.test(header)) {
581
+ lastValue = headers[header];
582
+ delete headers[header];
583
+ }
584
+ }
585
+ return (lastValue === null || typeof lastValue === "undefined") ?
586
+ undefined : String(lastValue).trim();
587
+ }
588
+
589
+ function createErrorType(code, message, baseClass) {
590
+ // Create constructor
591
+ function CustomError(properties) {
592
+ Error.captureStackTrace(this, this.constructor);
593
+ Object.assign(this, properties || {});
594
+ this.code = code;
595
+ this.message = this.cause ? message + ": " + this.cause.message : message;
596
+ }
597
+
598
+ // Attach constructor and set default properties
599
+ CustomError.prototype = new (baseClass || Error)();
600
+ CustomError.prototype.constructor = CustomError;
601
+ CustomError.prototype.name = "Error [" + code + "]";
602
+ return CustomError;
603
+ }
604
+
605
+ function destroyRequest(request, error) {
606
+ for (var event of events) {
607
+ request.removeListener(event, eventHandlers[event]);
608
+ }
609
+ request.on("error", noop);
610
+ request.destroy(error);
611
+ }
612
+
613
+ function isSubdomain(subdomain, domain) {
614
+ assert(isString(subdomain) && isString(domain));
615
+ var dot = subdomain.length - domain.length - 1;
616
+ return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
617
+ }
618
+
619
+ function isString(value) {
620
+ return typeof value === "string" || value instanceof String;
621
+ }
622
+
623
+ function isFunction(value) {
624
+ return typeof value === "function";
625
+ }
626
+
627
+ function isBuffer(value) {
628
+ return typeof value === "object" && ("length" in value);
629
+ }
630
+
631
+ // Exports
632
+ module.exports = wrap({ http: http, https: https });
633
+ module.exports.wrap = wrap;
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "follow-redirects",
3
+ "version": "1.15.3",
4
+ "description": "HTTP and HTTPS modules that follow redirects.",
5
+ "license": "MIT",
6
+ "main": "index.js",
7
+ "files": [
8
+ "*.js"
9
+ ],
10
+ "engines": {
11
+ "node": ">=4.0"
12
+ },
13
+ "scripts": {
14
+ "lint": "eslint *.js test",
15
+ "test": "nyc mocha"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git@github.com:follow-redirects/follow-redirects.git"
20
+ },
21
+ "homepage": "https://github.com/follow-redirects/follow-redirects",
22
+ "bugs": {
23
+ "url": "https://github.com/follow-redirects/follow-redirects/issues"
24
+ },
25
+ "keywords": [
26
+ "http",
27
+ "https",
28
+ "url",
29
+ "redirect",
30
+ "client",
31
+ "location",
32
+ "utility"
33
+ ],
34
+ "author": "Ruben Verborgh <ruben@verborgh.org> (https://ruben.verborgh.org/)",
35
+ "contributors": [
36
+ "Olivier Lalonde <olalonde@gmail.com> (http://www.syskall.com)",
37
+ "James Talmage <james@talmage.io>"
38
+ ],
39
+ "funding": [
40
+ {
41
+ "type": "individual",
42
+ "url": "https://github.com/sponsors/RubenVerborgh"
43
+ }
44
+ ],
45
+ "peerDependenciesMeta": {
46
+ "debug": {
47
+ "optional": true
48
+ }
49
+ },
50
+ "devDependencies": {
51
+ "concat-stream": "^2.0.0",
52
+ "eslint": "^5.16.0",
53
+ "express": "^4.16.4",
54
+ "lolex": "^3.1.0",
55
+ "mocha": "^6.0.2",
56
+ "nyc": "^14.1.1"
57
+ }
58
+ }
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.