@verdaccio/proxy 6.0.0-6-next.18 → 6.0.0-6-next.21

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.
@@ -1,693 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.ProxyStorage = void 0;
7
-
8
- var _JSONStream = _interopRequireDefault(require("JSONStream"));
9
-
10
- var _debug = _interopRequireDefault(require("debug"));
11
-
12
- var _lodash = _interopRequireDefault(require("lodash"));
13
-
14
- var _request = _interopRequireDefault(require("request"));
15
-
16
- var _stream = _interopRequireWildcard(require("stream"));
17
-
18
- var _undiciFetch = require("undici-fetch");
19
-
20
- var _url = require("url");
21
-
22
- var _core = require("@verdaccio/core");
23
-
24
- var _streams = require("@verdaccio/streams");
25
-
26
- var _utils = require("@verdaccio/utils");
27
-
28
- var _proxyUtils = require("./proxy-utils");
29
-
30
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
31
-
32
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
33
-
34
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
35
-
36
- /* global AbortController */
37
- const LoggerApi = require('@verdaccio/logger');
38
-
39
- const fetch = require('undici-fetch');
40
-
41
- const debug = (0, _debug.default)('verdaccio:proxy');
42
-
43
- const encode = function (thing) {
44
- return encodeURIComponent(thing).replace(/^%40/, '@');
45
- };
46
-
47
- const jsonContentType = _core.HEADERS.JSON;
48
- const contentTypeAccept = `${jsonContentType};`;
49
- /**
50
- * Just a helper (`config[key] || default` doesn't work because of zeroes)
51
- */
52
-
53
- const setConfig = (config, key, def) => {
54
- return _lodash.default.isNil(config[key]) === false ? config[key] : def;
55
- };
56
-
57
- /**
58
- * Implements Storage interface
59
- * (same for storage.js, local-storage.js, up-storage.js)
60
- */
61
- class ProxyStorage {
62
- // FIXME: upname is assigned to each instance
63
- // @ts-ignore
64
- // FIXME: proxy can be boolean or object, something smells here
65
- // @ts-ignore
66
- // @ts-ignore
67
-
68
- /**
69
- * Constructor
70
- * @param {*} config
71
- * @param {*} mainConfig
72
- */
73
- constructor(config, mainConfig) {
74
- this.config = config;
75
- this.failed_requests = 0;
76
- this.userAgent = mainConfig.user_agent;
77
- this.ca = config.ca;
78
- this.logger = LoggerApi.logger.child({
79
- sub: 'out'
80
- });
81
- this.server_id = mainConfig.server_id;
82
- this.url = new _url.URL(this.config.url);
83
-
84
- this._setupProxy(this.url.hostname, config, mainConfig, this.url.protocol === 'https:');
85
-
86
- this.config.url = this.config.url.replace(/\/$/, '');
87
-
88
- if (this.config.timeout && Number(this.config.timeout) >= 1000) {
89
- this.logger.warn(['Too big timeout value: ' + this.config.timeout, 'We changed time format to nginx-like one', '(see http://nginx.org/en/docs/syntax.html)', 'so please update your config accordingly'].join('\n'));
90
- } // a bunch of different configurable timers
91
-
92
-
93
- this.maxage = (0, _proxyUtils.parseInterval)(setConfig(this.config, 'maxage', '2m'));
94
- this.timeout = (0, _proxyUtils.parseInterval)(setConfig(this.config, 'timeout', '30s'));
95
- this.max_fails = Number(setConfig(this.config, 'max_fails', 2));
96
- this.fail_timeout = (0, _proxyUtils.parseInterval)(setConfig(this.config, 'fail_timeout', '5m'));
97
- this.strict_ssl = Boolean(setConfig(this.config, 'strict_ssl', true));
98
- this.agent_options = setConfig(this.config, 'agent_options', {
99
- keepAlive: true,
100
- maxSockets: 40,
101
- maxFreeSockets: 10
102
- });
103
- }
104
- /**
105
- * Fetch an asset.
106
- * @param {*} options
107
- * @param {*} cb
108
- * @return {Request}
109
- */
110
-
111
-
112
- request(options, cb) {
113
- let json;
114
-
115
- if (this._statusCheck() === false) {
116
- const streamRead = new _stream.default.Readable();
117
- process.nextTick(function () {
118
- if (cb) {
119
- cb(_core.errorUtils.getInternalError(_core.errorUtils.API_ERROR.UPLINK_OFFLINE));
120
- }
121
-
122
- streamRead.emit('error', _core.errorUtils.getInternalError(_core.errorUtils.API_ERROR.UPLINK_OFFLINE));
123
- });
124
-
125
- streamRead._read = function () {}; // preventing 'Uncaught, unspecified "error" event'
126
-
127
-
128
- streamRead.on('error', function () {});
129
- return streamRead;
130
- }
131
-
132
- const self = this;
133
-
134
- const headers = this._setHeaders(options);
135
-
136
- this._addProxyHeaders(options.req, headers);
137
-
138
- this._overrideWithUpLinkConfLocaligHeaders(headers);
139
-
140
- const method = options.method || 'GET';
141
- const uri = options.uri_full || this.config.url + options.uri;
142
- self.logger.info({
143
- method: method,
144
- headers: headers,
145
- uri: uri
146
- }, "making request: '@{method} @{uri}'");
147
-
148
- if (_core.validatioUtils.isObject(options.json)) {
149
- json = JSON.stringify(options.json);
150
- headers['Content-Type'] = headers['Content-Type'] || _core.HEADERS.JSON;
151
- }
152
-
153
- const requestCallback = cb ? function (err, res, body) {
154
- let error;
155
- const responseLength = err ? 0 : body.length; // $FlowFixMe
156
-
157
- processBody();
158
- logActivity(); // $FlowFixMe
159
-
160
- cb(err, res, body);
161
- /**
162
- * Perform a decode.
163
- */
164
-
165
- function processBody() {
166
- if (err) {
167
- error = err.message;
168
- return;
169
- }
170
-
171
- if (options.json && res.statusCode < 300) {
172
- try {
173
- // $FlowFixMe
174
- body = JSON.parse(body.toString(_core.CHARACTER_ENCODING.UTF8));
175
- } catch (_err) {
176
- body = {};
177
- err = _err;
178
- error = err.message;
179
- }
180
- }
181
-
182
- if (!err && _core.validatioUtils.isObject(body)) {
183
- if (_lodash.default.isString(body.error)) {
184
- error = body.error;
185
- }
186
- }
187
- }
188
- /**
189
- * Perform a log.
190
- */
191
-
192
-
193
- function logActivity() {
194
- let message = "@{!status}, req: '@{request.method} @{request.url}'"; // FIXME: use LOG_VERDACCIO_BYTES
195
-
196
- message += error ? ', error: @{!error}' : ', bytes: @{bytes.in}/@{bytes.out}';
197
- self.logger.http({
198
- // if error is null/false change this to undefined so it wont log
199
- err: err || undefined,
200
- request: {
201
- method: method,
202
- url: uri
203
- },
204
- status: res != null ? res.statusCode : 'ERR',
205
- error: error,
206
- bytes: {
207
- in: json ? json.length : 0,
208
- out: responseLength || 0
209
- }
210
- }, message);
211
- }
212
- } : undefined;
213
- let requestOptions = {
214
- url: uri,
215
- method: method,
216
- headers: headers,
217
- body: json,
218
- proxy: this.proxy,
219
- encoding: null,
220
- gzip: true,
221
- timeout: this.timeout,
222
- strictSSL: this.strict_ssl,
223
- agentOptions: this.agent_options
224
- };
225
-
226
- if (this.ca) {
227
- requestOptions = Object.assign({}, requestOptions, {
228
- ca: this.ca
229
- });
230
- }
231
-
232
- const req = (0, _request.default)(requestOptions, requestCallback);
233
- let statusCalled = false;
234
- req.on('response', function (res) {
235
- // FIXME: _verdaccio_aborted seems not used
236
- // @ts-ignore
237
- if (!req._verdaccio_aborted && !statusCalled) {
238
- statusCalled = true;
239
-
240
- self._statusCheck(true);
241
- }
242
-
243
- if (_lodash.default.isNil(requestCallback) === false) {
244
- (function do_log() {
245
- const message = "@{!status}, req: '@{request.method} @{request.url}' (streaming)";
246
- self.logger.http({
247
- request: {
248
- method: method,
249
- url: uri
250
- },
251
- status: _lodash.default.isNull(res) === false ? res.statusCode : 'ERR'
252
- }, message);
253
- })();
254
- }
255
- }); // eslint-disable-next-line @typescript-eslint/no-unused-vars
256
-
257
- req.on('error', function (_err) {
258
- // FIXME: _verdaccio_aborted seems not used
259
- // @ts-ignore
260
- if (!req._verdaccio_aborted && !statusCalled) {
261
- statusCalled = true;
262
-
263
- self._statusCheck(false);
264
- }
265
- }); // @ts-ignore
266
-
267
- return req;
268
- }
269
- /**
270
- * Set default headers.
271
- * @param {Object} options
272
- * @return {Object}
273
- * @private
274
- */
275
-
276
-
277
- _setHeaders(options) {
278
- const headers = options.headers || {};
279
- const accept = _core.HEADERS.ACCEPT;
280
- const acceptEncoding = _core.HEADERS.ACCEPT_ENCODING;
281
- const userAgent = _core.HEADERS.USER_AGENT;
282
- headers[accept] = headers[accept] || contentTypeAccept;
283
- headers[acceptEncoding] = headers[acceptEncoding] || 'gzip'; // registry.npmjs.org will only return search result if user-agent include string 'npm'
284
-
285
- headers[userAgent] = headers[userAgent] || `npm (${this.userAgent})`;
286
- return this._setAuth(headers);
287
- }
288
- /**
289
- * Validate configuration auth and assign Header authorization
290
- * @param {Object} headers
291
- * @return {Object}
292
- * @private
293
- */
294
-
295
-
296
- _setAuth(headers) {
297
- const {
298
- auth
299
- } = this.config;
300
-
301
- if (_lodash.default.isNil(auth) || headers[_core.HEADERS.AUTHORIZATION]) {
302
- return headers;
303
- }
304
-
305
- if (_lodash.default.isObject(auth) === false && _lodash.default.isObject(auth.token) === false) {
306
- this._throwErrorAuth('Auth invalid');
307
- } // get NPM_TOKEN http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules
308
- // or get other variable export in env
309
- // https://github.com/verdaccio/verdaccio/releases/tag/v2.5.0
310
-
311
-
312
- let token;
313
- const tokenConf = auth;
314
-
315
- if (_lodash.default.isNil(tokenConf.token) === false && _lodash.default.isString(tokenConf.token)) {
316
- token = tokenConf.token;
317
- } else if (_lodash.default.isNil(tokenConf.token_env) === false) {
318
- if (_lodash.default.isString(tokenConf.token_env)) {
319
- token = process.env[tokenConf.token_env];
320
- } else if (_lodash.default.isBoolean(tokenConf.token_env) && tokenConf.token_env) {
321
- token = process.env.NPM_TOKEN;
322
- } else {
323
- this.logger.error(_core.constants.ERROR_CODE.token_required);
324
-
325
- this._throwErrorAuth(_core.constants.ERROR_CODE.token_required);
326
- }
327
- } else {
328
- token = process.env.NPM_TOKEN;
329
- }
330
-
331
- if (_lodash.default.isNil(token)) {
332
- this._throwErrorAuth(_core.constants.ERROR_CODE.token_required);
333
- } // define type Auth allow basic and bearer
334
-
335
-
336
- const type = tokenConf.type || _core.TOKEN_BASIC;
337
-
338
- this._setHeaderAuthorization(headers, type, token);
339
-
340
- return headers;
341
- }
342
- /**
343
- * @param {string} message
344
- * @throws {Error}
345
- * @private
346
- */
347
-
348
-
349
- _throwErrorAuth(message) {
350
- this.logger.error(message);
351
- throw new Error(message);
352
- }
353
- /**
354
- * Assign Header authorization with type authentication
355
- * @param {Object} headers
356
- * @param {string} type
357
- * @param {string} token
358
- * @private
359
- */
360
-
361
-
362
- _setHeaderAuthorization(headers, type, token) {
363
- const _type = type.toLowerCase();
364
-
365
- if (_type !== _core.TOKEN_BEARER.toLowerCase() && _type !== _core.TOKEN_BASIC.toLowerCase()) {
366
- this._throwErrorAuth(`Auth type '${_type}' not allowed`);
367
- }
368
-
369
- type = _lodash.default.upperFirst(type);
370
- headers[_core.HEADERS.AUTHORIZATION] = (0, _utils.buildToken)(type, token);
371
- }
372
- /**
373
- * It will add or override specified headers from config file.
374
- *
375
- * Eg:
376
- *
377
- * uplinks:
378
- npmjs:
379
- url: https://registry.npmjs.org/
380
- headers:
381
- Accept: "application/vnd.npm.install-v2+json; q=1.0"
382
- verdaccio-staging:
383
- url: https://mycompany.com/npm
384
- headers:
385
- Accept: "application/json"
386
- authorization: "Basic YourBase64EncodedCredentials=="
387
- * @param {Object} headers
388
- * @private
389
- */
390
-
391
-
392
- _overrideWithUpLinkConfLocaligHeaders(headers) {
393
- if (!this.config.headers) {
394
- return headers;
395
- } // add/override headers specified in the config
396
-
397
- /* eslint guard-for-in: 0 */
398
-
399
-
400
- for (const key in this.config.headers) {
401
- headers[key] = this.config.headers[key];
402
- }
403
- }
404
- /**
405
- * Get a remote package metadata
406
- * @param {*} name package name
407
- * @param {*} options request options, eg: eTag.
408
- * @param {*} callback
409
- */
410
-
411
-
412
- getRemoteMetadata(name, options, callback) {
413
- const headers = {};
414
-
415
- if (_lodash.default.isNil(options.etag) === false) {
416
- headers['If-None-Match'] = options.etag;
417
- headers[_core.HEADERS.ACCEPT] = contentTypeAccept;
418
- }
419
-
420
- this.request({
421
- uri: `/${encode(name)}`,
422
- json: true,
423
- headers: headers,
424
- req: options.req
425
- }, (err, res, body) => {
426
- if (err) {
427
- return callback(err);
428
- }
429
-
430
- if (res.statusCode === _core.HTTP_STATUS.NOT_FOUND) {
431
- return callback(_core.errorUtils.getNotFound(_core.errorUtils.API_ERROR.NOT_PACKAGE_UPLINK));
432
- }
433
-
434
- if (!(res.statusCode >= _core.HTTP_STATUS.OK && res.statusCode < _core.HTTP_STATUS.MULTIPLE_CHOICES)) {
435
- const error = _core.errorUtils.getInternalError(`${_core.errorUtils.API_ERROR.BAD_STATUS_CODE}: ${res.statusCode}`);
436
-
437
- error.remoteStatus = res.statusCode;
438
- return callback(error);
439
- }
440
-
441
- callback(null, body, res.headers.etag);
442
- });
443
- }
444
- /**
445
- * Fetch a tarball from the uplink.
446
- * @param {String} url
447
- * @return {Stream}
448
- */
449
-
450
-
451
- fetchTarball(url) {
452
- const stream = new _streams.ReadTarball({});
453
- let current_length = 0;
454
- let expected_length;
455
-
456
- stream.abort = () => {};
457
-
458
- const readStream = this.request({
459
- uri_full: url,
460
- encoding: null,
461
- headers: {
462
- Accept: contentTypeAccept
463
- }
464
- });
465
- readStream.on('response', function (res) {
466
- if (res.statusCode === _core.HTTP_STATUS.NOT_FOUND) {
467
- return stream.emit('error', _core.errorUtils.getNotFound(_core.errorUtils.API_ERROR.NOT_FILE_UPLINK));
468
- }
469
-
470
- if (!(res.statusCode >= _core.HTTP_STATUS.OK && res.statusCode < _core.HTTP_STATUS.MULTIPLE_CHOICES)) {
471
- return stream.emit('error', _core.errorUtils.getInternalError(`bad uplink status code: ${res.statusCode}`));
472
- }
473
-
474
- if (res.headers[_core.HEADER_TYPE.CONTENT_LENGTH]) {
475
- expected_length = res.headers[_core.HEADER_TYPE.CONTENT_LENGTH];
476
- stream.emit(_core.HEADER_TYPE.CONTENT_LENGTH, res.headers[_core.HEADER_TYPE.CONTENT_LENGTH]);
477
- }
478
-
479
- readStream.pipe(stream);
480
- });
481
- readStream.on('error', function (err) {
482
- stream.emit('error', err);
483
- });
484
- readStream.on('data', function (data) {
485
- current_length += data.length;
486
- });
487
- readStream.on('end', function (data) {
488
- if (data) {
489
- current_length += data.length;
490
- }
491
-
492
- if (expected_length && current_length != expected_length) {
493
- stream.emit('error', _core.errorUtils.getInternalError(_core.errorUtils.API_ERROR.CONTENT_MISMATCH));
494
- }
495
- });
496
- return stream;
497
- }
498
- /**
499
- * Perform a stream search.
500
- * @param {*} options request options
501
- * @return {Stream}
502
- */
503
-
504
-
505
- async search({
506
- url,
507
- abort
508
- }) {
509
- debug('search url %o', url);
510
- let response;
511
-
512
- try {
513
- const fullURL = new _url.URL(`${this.url}${url}`); // FIXME: a better way to remove duplicate slashes?
514
-
515
- const uri = fullURL.href.replace(/([^:]\/)\/+/g, '$1');
516
- this.logger.http({
517
- uri,
518
- uplink: this.upname
519
- }, 'search request to uplink @{uplink} - @{uri}');
520
- const request = new _undiciFetch.Request(uri, {
521
- method: 'GET',
522
- // FUTURE: whitelist domains what we are sending not need it headers, security check
523
- // headers: new Headers({
524
- // ...headers,
525
- // connection: 'keep-alive',
526
- // }),
527
- signal: abort === null || abort === void 0 ? void 0 : abort.signal
528
- });
529
- response = await fetch(request);
530
- debug('response.status %o', response.status);
531
-
532
- if (response.status >= _core.HTTP_STATUS.BAD_REQUEST) {
533
- throw _core.errorUtils.getInternalError(`bad status code ${response.status} from uplink`);
534
- }
535
-
536
- const streamSearch = new _stream.PassThrough({
537
- objectMode: true
538
- });
539
- const res = await response.text();
540
-
541
- const streamResponse = _stream.Readable.from(res); // objects is one of the properties on the body, it ignores date and total
542
-
543
-
544
- streamResponse.pipe(_JSONStream.default.parse('objects')).pipe(streamSearch, {
545
- end: true
546
- });
547
- return streamSearch;
548
- } catch (err) {
549
- this.logger.error({
550
- errorMessage: err === null || err === void 0 ? void 0 : err.message
551
- }, 'proxy search error: @{errorMessage}');
552
- throw err;
553
- }
554
- }
555
- /**
556
- * Add proxy headers.
557
- * FIXME: object mutations, it should return an new object
558
- * @param {*} req the http request
559
- * @param {*} headers the request headers
560
- */
561
-
562
-
563
- _addProxyHeaders(req, headers) {
564
- if (req) {
565
- // Only submit X-Forwarded-For field if we don't have a proxy selected
566
- // in the config file.
567
- //
568
- // Otherwise misconfigured proxy could return 407:
569
- // https://github.com/rlidwka/sinopia/issues/254
570
- // @ts-ignore
571
- if (!this.proxy) {
572
- headers[_core.HEADERS.FORWARDED_FOR] = (req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'] + ', ' : '') + req.connection.remoteAddress;
573
- }
574
- } // always attach Via header to avoid loops, even if we're not proxying
575
-
576
-
577
- headers['Via'] = req !== null && req !== void 0 && req.headers['via'] ? req.headers['via'] + ', ' : '';
578
- headers['Via'] += '1.1 ' + this.server_id + ' (Verdaccio)';
579
- }
580
- /**
581
- * Check whether the remote host is available.
582
- * @param {*} alive
583
- * @return {Boolean}
584
- */
585
-
586
-
587
- _statusCheck(alive) {
588
- if (arguments.length === 0) {
589
- return this._ifRequestFailure() === false;
590
- }
591
-
592
- if (alive) {
593
- if (this.failed_requests >= this.max_fails) {
594
- this.logger.warn({
595
- host: this.url.host
596
- }, 'host @{host} is back online');
597
- }
598
-
599
- this.failed_requests = 0;
600
- } else {
601
- this.failed_requests++;
602
-
603
- if (this.failed_requests === this.max_fails) {
604
- this.logger.warn({
605
- host: this.url.host
606
- }, 'host @{host} is now offline');
607
- }
608
- }
609
-
610
- this.last_request_time = Date.now();
611
- }
612
- /**
613
- * If the request failure.
614
- * @return {boolean}
615
- * @private
616
- */
617
-
618
-
619
- _ifRequestFailure() {
620
- return this.failed_requests >= this.max_fails && Math.abs(Date.now() - this.last_request_time) < this.fail_timeout;
621
- }
622
- /**
623
- * Set up a proxy.
624
- * @param {*} hostname
625
- * @param {*} config
626
- * @param {*} mainconfig
627
- * @param {*} isHTTPS
628
- */
629
-
630
-
631
- _setupProxy(hostname, config, mainconfig, isHTTPS) {
632
- let noProxyList;
633
- const proxy_key = isHTTPS ? 'https_proxy' : 'http_proxy'; // get http_proxy and no_proxy configs
634
-
635
- if (proxy_key in config) {
636
- this.proxy = config[proxy_key];
637
- } else if (proxy_key in mainconfig) {
638
- this.proxy = mainconfig[proxy_key];
639
- }
640
-
641
- if ('no_proxy' in config) {
642
- noProxyList = config.no_proxy;
643
- } else if ('no_proxy' in mainconfig) {
644
- noProxyList = mainconfig.no_proxy;
645
- } // use wget-like algorithm to determine if proxy shouldn't be used
646
-
647
-
648
- if (hostname[0] !== '.') {
649
- hostname = '.' + hostname;
650
- }
651
-
652
- if (_lodash.default.isString(noProxyList) && noProxyList.length) {
653
- noProxyList = noProxyList.split(',');
654
- }
655
-
656
- if (_lodash.default.isArray(noProxyList)) {
657
- for (let i = 0; i < noProxyList.length; i++) {
658
- let noProxyItem = noProxyList[i];
659
-
660
- if (noProxyItem[0] !== '.') {
661
- noProxyItem = '.' + noProxyItem;
662
- }
663
-
664
- if (hostname.lastIndexOf(noProxyItem) === hostname.length - noProxyItem.length) {
665
- if (this.proxy) {
666
- this.logger.debug({
667
- url: this.url.href,
668
- rule: noProxyItem
669
- }, 'not using proxy for @{url}, excluded by @{rule} rule'); // @ts-ignore
670
-
671
- this.proxy = false;
672
- }
673
-
674
- break;
675
- }
676
- }
677
- } // if it's non-string (i.e. "false"), don't use it
678
-
679
-
680
- if (_lodash.default.isString(this.proxy) === false) {
681
- delete this.proxy;
682
- } else {
683
- this.logger.debug({
684
- url: this.url.href,
685
- proxy: this.proxy
686
- }, 'using proxy @{proxy} for @{url}');
687
- }
688
- }
689
-
690
- }
691
-
692
- exports.ProxyStorage = ProxyStorage;
693
- //# sourceMappingURL=up-storage.js.map