@verdaccio/proxy 8.0.0-next-8.30 → 8.0.0-next-8.32

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.
package/build/proxy.js CHANGED
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  Object.defineProperty(exports, "FetchOptions", {
7
7
  enumerable: true,
8
- get: function () {
8
+ get: function get() {
9
9
  return _gotCjs.Options;
10
10
  }
11
11
  });
@@ -19,36 +19,50 @@ var _nodeUrl = require("node:url");
19
19
  var _core = require("@verdaccio/core");
20
20
  var _agent = _interopRequireDefault(require("./agent"));
21
21
  var _proxyUtils = require("./proxy-utils");
22
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
23
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
24
- const debug = (0, _debug.default)('verdaccio:proxy');
25
- const encode = function (thing) {
22
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t3 in e) "default" !== _t3 && {}.hasOwnProperty.call(e, _t3) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t3)) && (i.get || i.set) ? o(f, _t3, i) : f[_t3] = e[_t3]); return f; })(e, t); }
23
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
24
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
25
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
26
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
27
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
28
+ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
29
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
30
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
31
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
32
+ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
33
+ function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
34
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
35
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
36
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
37
+ var debug = (0, _debug["default"])('verdaccio:proxy');
38
+ var encode = function encode(thing) {
26
39
  return encodeURIComponent(thing).replace(/^%40/, '@');
27
40
  };
28
- const jsonContentType = _core.HEADERS.JSON;
29
- const contentTypeAccept = `${jsonContentType};`;
41
+ var jsonContentType = _core.HEADERS.JSON;
42
+ var contentTypeAccept = "".concat(jsonContentType, ";");
30
43
 
31
44
  /**
32
45
  * Just a helper (`config[key] || default` doesn't work because of zeroes)
33
46
  */
34
- const setConfig = (config, key, def) => {
35
- return _lodash.default.isNil(config[key]) === false ? config[key] : def;
47
+ var setConfig = function setConfig(config, key, def) {
48
+ return _lodash["default"].isNil(config[key]) === false ? config[key] : def;
36
49
  };
37
50
 
38
51
  // this type is need it by storage
39
-
40
52
  /**
41
53
  * Implements Storage interface
42
54
  * (same for storage.js, local-storage.js, up-storage.js)
43
55
  */
44
- class ProxyStorage {
56
+ var ProxyStorage = exports.ProxyStorage = /*#__PURE__*/function () {
45
57
  // @ts-ignore
46
58
 
47
- constructor(uplinkName, config, mainConfig, logger, agent) {
59
+ function ProxyStorage(uplinkName, config, mainConfig, logger, agent) {
60
+ var _mainConfig$user_agen, _this$config$max_fail, _this$max_fails;
61
+ _classCallCheck(this, ProxyStorage);
48
62
  this.uplinkName = uplinkName;
49
63
  this.config = config;
50
64
  this.failed_requests = 0;
51
- this.userAgent = mainConfig.user_agent ?? 'hidden';
65
+ this.userAgent = (_mainConfig$user_agen = mainConfig.user_agent) !== null && _mainConfig$user_agen !== void 0 ? _mainConfig$user_agen : 'hidden';
52
66
  this.ca = config.ca;
53
67
  this.logger = logger;
54
68
  this.server_id = mainConfig.server_id;
@@ -58,9 +72,9 @@ class ProxyStorage {
58
72
  maxFreeSockets: 10
59
73
  });
60
74
  this.url = new _nodeUrl.URL(this.config.url);
61
- const isHTTPS = this.url.protocol === 'https:';
75
+ var isHTTPS = this.url.protocol === 'https:';
62
76
  this._setupProxy(this.url.hostname, config, mainConfig, isHTTPS);
63
- this.agent = agent ?? this.getAgent();
77
+ this.agent = agent !== null && agent !== void 0 ? agent : this.getAgent();
64
78
  this.config.url = this.config.url.replace(/\/$/, '');
65
79
  if (this.config.timeout && Number(this.config.timeout) >= 1000) {
66
80
  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'));
@@ -73,436 +87,511 @@ class ProxyStorage {
73
87
  request: (0, _proxyUtils.parseInterval)(setConfig(this.config, 'timeout', '30s'))
74
88
  };
75
89
  debug('set timeout %s', this.timeout);
76
- this.max_fails = Number(setConfig(this.config, 'max_fails', this.config.max_fails ?? 2));
90
+ this.max_fails = Number(setConfig(this.config, 'max_fails', (_this$config$max_fail = this.config.max_fails) !== null && _this$config$max_fail !== void 0 ? _this$config$max_fail : 2));
77
91
  this.fail_timeout = (0, _proxyUtils.parseInterval)(setConfig(this.config, 'fail_timeout', '5m'));
78
92
  this.strict_ssl = Boolean(setConfig(this.config, 'strict_ssl', true));
79
93
  this.retry = {
80
- limit: this.max_fails ?? 2
94
+ limit: (_this$max_fails = this.max_fails) !== null && _this$max_fails !== void 0 ? _this$max_fails : 2
81
95
  };
82
96
  }
83
- getAgent() {
84
- if (!this.agent) {
85
- // TODO: the config.ca (certificates) is not yet injected here
86
- const agentInstance = new _agent.default(this.config.url, this.proxy, this.agent_options);
87
- return agentInstance.get();
88
- } else {
89
- return this.agent;
90
- }
91
- }
92
- getHeaders(headers = {}) {
93
- const accept = _core.HEADERS.ACCEPT;
94
- const acceptEncoding = _core.HEADERS.ACCEPT_ENCODING;
95
- const userAgent = _core.HEADERS.USER_AGENT;
96
- headers[accept] = headers[accept] || contentTypeAccept;
97
- headers[acceptEncoding] = headers[acceptEncoding] || 'gzip';
98
- // registry.npmjs.org will only return search result if user-agent include string 'npm'
99
- headers[userAgent] = headers[userAgent] || `npm (${this.userAgent})`;
100
- return this.setAuthNext(headers);
101
- }
102
-
103
- /**
104
- * Validate configuration auth and assign Header authorization
105
- * @param {Object} headers
106
- * @return {Object}
107
- * @private
108
- */
109
- setAuthNext(headers) {
110
- const {
111
- auth
112
- } = this.config;
113
- if (typeof auth === 'undefined' || typeof headers[_core.HEADERS.AUTHORIZATION] === 'string') {
114
- return headers;
97
+ return _createClass(ProxyStorage, [{
98
+ key: "getAgent",
99
+ value: function getAgent() {
100
+ if (!this.agent) {
101
+ // TODO: the config.ca (certificates) is not yet injected here
102
+ var agentInstance = new _agent["default"](this.config.url, this.proxy, this.agent_options);
103
+ return agentInstance.get();
104
+ } else {
105
+ return this.agent;
106
+ }
115
107
  }
116
- if (_lodash.default.isObject(auth) === false && _lodash.default.isObject(auth.token) === false) {
117
- this._throwErrorAuth('Auth invalid');
108
+ }, {
109
+ key: "getHeaders",
110
+ value: function getHeaders() {
111
+ var headers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
112
+ var accept = _core.HEADERS.ACCEPT;
113
+ var acceptEncoding = _core.HEADERS.ACCEPT_ENCODING;
114
+ var userAgent = _core.HEADERS.USER_AGENT;
115
+ headers[accept] = headers[accept] || contentTypeAccept;
116
+ headers[acceptEncoding] = headers[acceptEncoding] || 'gzip';
117
+ // registry.npmjs.org will only return search result if user-agent include string 'npm'
118
+ headers[userAgent] = headers[userAgent] || "npm (".concat(this.userAgent, ")");
119
+ return this.setAuthNext(headers);
118
120
  }
119
121
 
120
- // get NPM_TOKEN http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules
121
- // or get other variable export in env
122
- // https://github.com/verdaccio/verdaccio/releases/tag/v2.5.0
123
- let token;
124
- const tokenConf = auth;
125
- if (_lodash.default.isNil(tokenConf.token) === false && _lodash.default.isString(tokenConf.token)) {
126
- debug('use token from config');
127
- token = tokenConf.token;
128
- } else if (_lodash.default.isNil(tokenConf.token_env) === false) {
129
- if (typeof tokenConf.token_env === 'string') {
130
- debug('use token from env %o', tokenConf.token_env);
131
- token = process.env[tokenConf.token_env];
132
- } else if (typeof tokenConf.token_env === 'boolean' && tokenConf.token_env) {
122
+ /**
123
+ * Validate configuration auth and assign Header authorization
124
+ * @param {Object} headers
125
+ * @return {Object}
126
+ * @private
127
+ */
128
+ }, {
129
+ key: "setAuthNext",
130
+ value: function setAuthNext(headers) {
131
+ var auth = this.config.auth;
132
+ if (typeof auth === 'undefined' || typeof headers[_core.HEADERS.AUTHORIZATION] === 'string') {
133
+ return headers;
134
+ }
135
+ if (_lodash["default"].isObject(auth) === false && _lodash["default"].isObject(auth.token) === false) {
136
+ this._throwErrorAuth('Auth invalid');
137
+ }
138
+
139
+ // get NPM_TOKEN http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules
140
+ // or get other variable export in env
141
+ // https://github.com/verdaccio/verdaccio/releases/tag/v2.5.0
142
+ var token;
143
+ var tokenConf = auth;
144
+ if (_lodash["default"].isNil(tokenConf.token) === false && _lodash["default"].isString(tokenConf.token)) {
145
+ debug('use token from config');
146
+ token = tokenConf.token;
147
+ } else if (_lodash["default"].isNil(tokenConf.token_env) === false) {
148
+ if (typeof tokenConf.token_env === 'string') {
149
+ debug('use token from env %o', tokenConf.token_env);
150
+ token = process.env[tokenConf.token_env];
151
+ } else if (typeof tokenConf.token_env === 'boolean' && tokenConf.token_env) {
152
+ debug('use token from env NPM_TOKEN');
153
+ token = process.env.NPM_TOKEN;
154
+ } else {
155
+ this.logger.error(_core.constants.ERROR_CODE.token_required);
156
+ this._throwErrorAuth(_core.constants.ERROR_CODE.token_required);
157
+ }
158
+ } else {
133
159
  debug('use token from env NPM_TOKEN');
134
160
  token = process.env.NPM_TOKEN;
135
- } else {
136
- this.logger.error(_core.constants.ERROR_CODE.token_required);
161
+ }
162
+ if (typeof token === 'undefined') {
137
163
  this._throwErrorAuth(_core.constants.ERROR_CODE.token_required);
138
164
  }
139
- } else {
140
- debug('use token from env NPM_TOKEN');
141
- token = process.env.NPM_TOKEN;
142
- }
143
- if (typeof token === 'undefined') {
144
- this._throwErrorAuth(_core.constants.ERROR_CODE.token_required);
145
- }
146
165
 
147
- // define type Auth allow basic and bearer
148
- const type = tokenConf.type || _core.TOKEN_BASIC;
149
- debug('token type %o', type);
150
- this._setHeaderAuthorization(headers, type, token);
151
- return headers;
152
- }
153
-
154
- /**
155
- * @param {string} message
156
- * @throws {Error}
157
- * @private
158
- */
159
- _throwErrorAuth(message) {
160
- this.logger.error(message);
161
- throw new Error(message);
162
- }
163
-
164
- /**
165
- * Assign Header authorization with type authentication
166
- * @param {Object} headers
167
- * @param {string} type
168
- * @param {string} token
169
- * @private
170
- */
171
- _setHeaderAuthorization(headers, type, token) {
172
- const _type = type.toLowerCase();
173
- if (_type !== _core.TOKEN_BEARER.toLowerCase() && _type !== _core.TOKEN_BASIC.toLowerCase()) {
174
- this._throwErrorAuth(`Auth type '${_type}' not allowed`);
175
- }
176
- headers[_core.HEADERS.AUTHORIZATION] = _core.authUtils.buildToken(type, token);
177
- }
178
-
179
- /**
180
- * It will add or override specified headers from config file.
181
- *
182
- * Eg:
183
- *
184
- * uplinks:
185
- npmjs:
186
- url: https://registry.npmjs.org/
187
- headers:
188
- Accept: "application/vnd.npm.install-v2+json; q=1.0"
189
- verdaccio-staging:
190
- url: https://mycompany.com/npm
191
- headers:
192
- Accept: "application/json"
193
- authorization: "Basic YourBase64EncodedCredentials=="
194
- * @param {Object} headers
195
- * @private
196
- */
197
- applyUplinkHeaders(headers) {
198
- if (!this.config.headers) {
166
+ // define type Auth allow basic and bearer
167
+ var type = tokenConf.type || _core.TOKEN_BASIC;
168
+ debug('token type %o', type);
169
+ this._setHeaderAuthorization(headers, type, token);
199
170
  return headers;
200
171
  }
201
172
 
202
- // add/override headers specified in the config
203
- /* eslint guard-for-in: 0 */
204
- for (const key in this.config.headers) {
205
- headers[key] = this.config.headers[key];
173
+ /**
174
+ * @param {string} message
175
+ * @throws {Error}
176
+ * @private
177
+ */
178
+ }, {
179
+ key: "_throwErrorAuth",
180
+ value: function _throwErrorAuth(message) {
181
+ this.logger.error(message);
182
+ throw new Error(message);
206
183
  }
207
- return headers;
208
- }
209
- async getRemoteMetadata(name, options) {
210
- if (this._ifRequestFailure()) {
211
- throw _core.errorUtils.getInternalError(_core.API_ERROR.UPLINK_OFFLINE);
184
+
185
+ /**
186
+ * Assign Header authorization with type authentication
187
+ * @param {Object} headers
188
+ * @param {string} type
189
+ * @param {string} token
190
+ * @private
191
+ */
192
+ }, {
193
+ key: "_setHeaderAuthorization",
194
+ value: function _setHeaderAuthorization(headers, type, token) {
195
+ var _type = type.toLowerCase();
196
+ if (_type !== _core.TOKEN_BEARER.toLowerCase() && _type !== _core.TOKEN_BASIC.toLowerCase()) {
197
+ this._throwErrorAuth("Auth type '".concat(_type, "' not allowed"));
198
+ }
199
+ headers[_core.HEADERS.AUTHORIZATION] = _core.authUtils.buildToken(type, token);
212
200
  }
213
201
 
214
- // FUTURE: allow mix headers that comes from the client
215
- debug('getting metadata for package %s', name);
216
- let headers = this.getHeaders(options?.headers);
217
- headers = this.addProxyHeaders(headers, options.remoteAddress);
218
- headers = this.applyUplinkHeaders(headers);
219
- // the following headers cannot be overwritten
220
- if (_lodash.default.isNil(options.etag) === false) {
221
- headers[_core.HEADERS.NONE_MATCH] = options.etag;
222
- headers[_core.HEADERS.ACCEPT] = contentTypeAccept;
202
+ /**
203
+ * It will add or override specified headers from config file.
204
+ *
205
+ * Eg:
206
+ *
207
+ * uplinks:
208
+ npmjs:
209
+ url: https://registry.npmjs.org/
210
+ headers:
211
+ Accept: "application/vnd.npm.install-v2+json; q=1.0"
212
+ verdaccio-staging:
213
+ url: https://mycompany.com/npm
214
+ headers:
215
+ Accept: "application/json"
216
+ authorization: "Basic YourBase64EncodedCredentials=="
217
+ * @param {Object} headers
218
+ * @private
219
+ */
220
+ }, {
221
+ key: "applyUplinkHeaders",
222
+ value: function applyUplinkHeaders(headers) {
223
+ if (!this.config.headers) {
224
+ return headers;
225
+ }
226
+
227
+ // add/override headers specified in the config
228
+ /* eslint guard-for-in: 0 */
229
+ for (var _key in this.config.headers) {
230
+ headers[_key] = this.config.headers[_key];
231
+ }
232
+ return headers;
223
233
  }
224
- const method = options.method || 'GET';
225
- const uri = this.config.url + `/${encode(name)}`;
226
- debug('set retry limit is %s', this.retry.limit);
227
- let response;
228
- let responseLength = 0;
229
- try {
230
- const retry = options?.retry ?? this.retry;
231
- debug('retry initial count %s', retry);
232
- response = await (0, _gotCjs.default)(uri, {
233
- headers,
234
- responseType: 'json',
235
- method,
236
- agent: this.agent,
237
- retry,
238
- timeout: this.timeout,
239
- hooks: {
240
- afterResponse: [afterResponse => {
241
- const code = afterResponse.statusCode;
242
- debug('after response code is %s', code);
243
- if (code >= _core.HTTP_STATUS.OK && code < _core.HTTP_STATUS.MULTIPLE_CHOICES) {
244
- if (this.failed_requests >= this.max_fails) {
245
- this.failed_requests = 0;
246
- this.logger.warn({
247
- host: this.url.host
248
- }, 'host @{host} is now online');
234
+ }, {
235
+ key: "getRemoteMetadata",
236
+ value: function () {
237
+ var _getRemoteMetadata = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(name, options) {
238
+ var _this = this;
239
+ var headers, method, uri, response, responseLength, _options$retry, _response, retry, etag, data, message, code, error, _t;
240
+ return _regenerator().w(function (_context) {
241
+ while (1) switch (_context.p = _context.n) {
242
+ case 0:
243
+ if (!this._ifRequestFailure()) {
244
+ _context.n = 1;
245
+ break;
249
246
  }
250
- }
251
- return afterResponse;
252
- }],
253
- beforeRetry: [(error, count) => {
254
- debug('retry %s count: %s', uri, count);
255
- this.failed_requests = count ?? 0;
256
- this.logger.info({
257
- request: {
247
+ throw _core.errorUtils.getInternalError(_core.API_ERROR.UPLINK_OFFLINE);
248
+ case 1:
249
+ // FUTURE: allow mix headers that comes from the client
250
+ debug('getting metadata for package %s', name);
251
+ headers = this.getHeaders(options === null || options === void 0 ? void 0 : options.headers);
252
+ headers = this.addProxyHeaders(headers, options.remoteAddress);
253
+ headers = this.applyUplinkHeaders(headers);
254
+ // the following headers cannot be overwritten
255
+ if (_lodash["default"].isNil(options.etag) === false) {
256
+ headers[_core.HEADERS.NONE_MATCH] = options.etag;
257
+ headers[_core.HEADERS.ACCEPT] = contentTypeAccept;
258
+ }
259
+ method = options.method || 'GET';
260
+ uri = this.config.url + "/".concat(encode(name));
261
+ debug('set retry limit is %s', this.retry.limit);
262
+ responseLength = 0;
263
+ _context.p = 2;
264
+ retry = (_options$retry = options === null || options === void 0 ? void 0 : options.retry) !== null && _options$retry !== void 0 ? _options$retry : this.retry;
265
+ debug('retry initial count %s', retry);
266
+ _context.n = 3;
267
+ return (0, _gotCjs["default"])(uri, {
268
+ headers: headers,
269
+ responseType: 'json',
258
270
  method: method,
259
- url: uri
260
- },
261
- error: error.message,
262
- retryCount: this.failed_requests
263
- }, "retry @{retryCount} req: '@{request.method} @{request.url}'");
264
- if (this.failed_requests >= this.max_fails) {
265
- this.logger.warn({
266
- host: this.url.host
267
- }, 'host @{host} is now offline');
268
- }
269
- }]
270
- }
271
- }).on('request', () => {
272
- this.last_request_time = Date.now();
273
- }).on('response', eventResponse => {
274
- const message = "@{!status}, req: '@{request.method} @{request.url}' (streaming)";
275
- this.logger.http({
276
- request: {
277
- method: method,
278
- url: uri
279
- },
280
- status: _lodash.default.isNull(eventResponse) === false ? eventResponse.statusCode : 'ERR'
281
- }, message);
282
- }).on('downloadProgress', progress => {
283
- if (progress.total) {
284
- debug('responseLength %s', progress.total);
285
- responseLength = progress.total;
286
- }
271
+ agent: this.agent,
272
+ retry: retry,
273
+ timeout: this.timeout,
274
+ hooks: {
275
+ afterResponse: [function (afterResponse) {
276
+ var code = afterResponse.statusCode;
277
+ debug('after response code is %s', code);
278
+ if (code >= _core.HTTP_STATUS.OK && code < _core.HTTP_STATUS.MULTIPLE_CHOICES) {
279
+ if (_this.failed_requests >= _this.max_fails) {
280
+ _this.failed_requests = 0;
281
+ _this.logger.warn({
282
+ host: _this.url.host
283
+ }, 'host @{host} is now online');
284
+ }
285
+ }
286
+ return afterResponse;
287
+ }],
288
+ beforeRetry: [function (error, count) {
289
+ debug('retry %s count: %s', uri, count);
290
+ _this.failed_requests = count !== null && count !== void 0 ? count : 0;
291
+ _this.logger.info({
292
+ request: {
293
+ method: method,
294
+ url: uri
295
+ },
296
+ error: error.message,
297
+ retryCount: _this.failed_requests
298
+ }, "retry @{retryCount} req: '@{request.method} @{request.url}'");
299
+ if (_this.failed_requests >= _this.max_fails) {
300
+ _this.logger.warn({
301
+ host: _this.url.host
302
+ }, 'host @{host} is now offline');
303
+ }
304
+ }]
305
+ }
306
+ }).on('request', function () {
307
+ _this.last_request_time = Date.now();
308
+ }).on('response', function (eventResponse) {
309
+ var message = "@{!status}, req: '@{request.method} @{request.url}' (streaming)";
310
+ _this.logger.http({
311
+ request: {
312
+ method: method,
313
+ url: uri
314
+ },
315
+ status: _lodash["default"].isNull(eventResponse) === false ? eventResponse.statusCode : 'ERR'
316
+ }, message);
317
+ }).on('downloadProgress', function (progress) {
318
+ if (progress.total) {
319
+ debug('responseLength %s', progress.total);
320
+ responseLength = progress.total;
321
+ }
322
+ });
323
+ case 3:
324
+ response = _context.v;
325
+ etag = response.headers.etag;
326
+ data = response.body; // not modified status (304) registry does not return any payload
327
+ // it is handled as an error
328
+ if (!(((_response = response) === null || _response === void 0 ? void 0 : _response.statusCode) === _core.HTTP_STATUS.NOT_MODIFIED)) {
329
+ _context.n = 4;
330
+ break;
331
+ }
332
+ throw _core.errorUtils.getCode(_core.HTTP_STATUS.NOT_MODIFIED, _core.API_ERROR.NOT_MODIFIED_NO_DATA);
333
+ case 4:
334
+ debug('uri %s success', uri);
335
+ message = "@{!status}, req: '@{request.method} @{request.url}'";
336
+ this.logger.http({
337
+ // if error is null/false change this to undefined so it wont log
338
+ request: {
339
+ method: method,
340
+ url: uri
341
+ },
342
+ status: response.statusCode,
343
+ bytes: {
344
+ "in": options !== null && options !== void 0 && options.json ? JSON.stringify(options === null || options === void 0 ? void 0 : options.json).length : 0,
345
+ out: responseLength || 0
346
+ }
347
+ }, message);
348
+ return _context.a(2, [data, etag]);
349
+ case 5:
350
+ _context.p = 5;
351
+ _t = _context.v;
352
+ debug('error %s on uri %s', _t.code, uri);
353
+ if (!(_t.code === 'ERR_NON_2XX_3XX_RESPONSE')) {
354
+ _context.n = 8;
355
+ break;
356
+ }
357
+ code = _t.response.statusCode;
358
+ debug('error code %s', code);
359
+ if (!(code === _core.HTTP_STATUS.NOT_FOUND)) {
360
+ _context.n = 6;
361
+ break;
362
+ }
363
+ throw _core.errorUtils.getNotFound(_core.API_ERROR.NOT_PACKAGE_UPLINK);
364
+ case 6:
365
+ if (code >= _core.HTTP_STATUS.OK && code < _core.HTTP_STATUS.MULTIPLE_CHOICES) {
366
+ _context.n = 7;
367
+ break;
368
+ }
369
+ error = _core.errorUtils.getInternalError("".concat(_core.API_ERROR.BAD_STATUS_CODE, ": ").concat(code)); // we need this code to identify outside which status code triggered the error
370
+ error.remoteStatus = code;
371
+ throw error;
372
+ case 7:
373
+ _context.n = 9;
374
+ break;
375
+ case 8:
376
+ if (!this._isRequestTimeout(_t)) {
377
+ _context.n = 9;
378
+ break;
379
+ }
380
+ debug('error code timeout');
381
+ throw _core.errorUtils.getServiceUnavailable(_core.API_ERROR.SERVER_TIME_OUT);
382
+ case 9:
383
+ throw _t;
384
+ case 10:
385
+ return _context.a(2);
386
+ }
387
+ }, _callee, this, [[2, 5]]);
388
+ }));
389
+ function getRemoteMetadata(_x, _x2) {
390
+ return _getRemoteMetadata.apply(this, arguments);
391
+ }
392
+ return getRemoteMetadata;
393
+ }() // FIXME: handle stream and retry
394
+ }, {
395
+ key: "fetchTarball",
396
+ value: function fetchTarball(url, overrideOptions) {
397
+ var _this$retry,
398
+ _this2 = this;
399
+ debug('fetching url for %s', url);
400
+ var options = _objectSpread(_objectSpread({}, this.config), overrideOptions);
401
+ var headers = this.getHeaders(options === null || options === void 0 ? void 0 : options.headers);
402
+ headers = this.addProxyHeaders(headers, options.remoteAddress);
403
+ headers = this.applyUplinkHeaders(headers);
404
+ // the following headers cannot be overwritten
405
+ if (_lodash["default"].isNil(options.etag) === false) {
406
+ headers[_core.HEADERS.NONE_MATCH] = options.etag;
407
+ headers[_core.HEADERS.ACCEPT] = contentTypeAccept;
408
+ }
409
+ var method = 'GET';
410
+ // const uri = this.config.url + `/${encode(name)}`;
411
+ debug('request uri for %s', url);
412
+ var readStream = _gotCjs["default"].stream(url, {
413
+ headers: headers,
414
+ method: method,
415
+ agent: this.agent,
416
+ // FIXME: this should be taken from construtor as priority
417
+ retry: (_this$retry = this.retry) !== null && _this$retry !== void 0 ? _this$retry : options === null || options === void 0 ? void 0 : options.retry,
418
+ timeout: this.timeout
419
+ }).on('request', function () {
420
+ _this2.last_request_time = Date.now();
287
421
  });
288
- const etag = response.headers.etag;
289
- const data = response.body;
422
+ return readStream;
423
+ }
290
424
 
291
- // not modified status (304) registry does not return any payload
292
- // it is handled as an error
293
- if (response?.statusCode === _core.HTTP_STATUS.NOT_MODIFIED) {
294
- throw _core.errorUtils.getCode(_core.HTTP_STATUS.NOT_MODIFIED, _core.API_ERROR.NOT_MODIFIED_NO_DATA);
425
+ /**
426
+ * Perform a stream search.
427
+ * @param {*} options request options
428
+ * @return {Stream}
429
+ */
430
+ }, {
431
+ key: "search",
432
+ value: (function () {
433
+ var _search = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(_ref) {
434
+ var url, abort, retry, uri, response, res, total, streamSearch, streamResponse, _t2;
435
+ return _regenerator().w(function (_context2) {
436
+ while (1) switch (_context2.p = _context2.n) {
437
+ case 0:
438
+ url = _ref.url, abort = _ref.abort, retry = _ref.retry;
439
+ _context2.p = 1;
440
+ // Incoming URL is relative ie /-/v1/search...
441
+ uri = new _nodeUrl.URL(url, this.url).href;
442
+ this.logger.http({
443
+ uri: uri,
444
+ uplink: this.uplinkName
445
+ }, 'search request to uplink @{uplink} - @{uri}');
446
+ debug('searching on %o', uri);
447
+ response = (0, _gotCjs["default"])(uri, {
448
+ signal: abort ? abort.signal : {},
449
+ agent: this.agent,
450
+ timeout: this.timeout,
451
+ retry: retry !== null && retry !== void 0 ? retry : this.retry
452
+ });
453
+ _context2.n = 2;
454
+ return response.text();
455
+ case 2:
456
+ res = _context2.v;
457
+ total = JSON.parse(res).total;
458
+ debug('number of packages found: %o', total);
459
+ streamSearch = new _nodeStream.PassThrough({
460
+ objectMode: true
461
+ });
462
+ streamResponse = _nodeStream.Readable.from(res); // objects is one of the properties on the body, it ignores date and total
463
+ streamResponse.pipe(_JSONStream["default"].parse('objects')).pipe(streamSearch, {
464
+ end: true
465
+ });
466
+ return _context2.a(2, streamSearch);
467
+ case 3:
468
+ _context2.p = 3;
469
+ _t2 = _context2.v;
470
+ debug('search error %s', _t2);
471
+ if (!(_t2.response.statusCode === 409)) {
472
+ _context2.n = 4;
473
+ break;
474
+ }
475
+ throw _core.errorUtils.getInternalError("bad status code ".concat(_t2.response.statusCode, " from uplink"));
476
+ case 4:
477
+ this.logger.error({
478
+ errorMessage: _t2 === null || _t2 === void 0 ? void 0 : _t2.message,
479
+ name: this.uplinkName
480
+ }, 'proxy uplink @{name} search error: @{errorMessage}');
481
+ throw _t2;
482
+ case 5:
483
+ return _context2.a(2);
484
+ }
485
+ }, _callee2, this, [[1, 3]]);
486
+ }));
487
+ function search(_x3) {
488
+ return _search.apply(this, arguments);
295
489
  }
296
- debug('uri %s success', uri);
297
- const message = "@{!status}, req: '@{request.method} @{request.url}'";
298
- this.logger.http({
299
- // if error is null/false change this to undefined so it wont log
300
- request: {
301
- method: method,
302
- url: uri
303
- },
304
- status: response.statusCode,
305
- bytes: {
306
- in: options?.json ? JSON.stringify(options?.json).length : 0,
307
- out: responseLength || 0
308
- }
309
- }, message);
310
- return [data, etag];
311
- } catch (err) {
312
- debug('error %s on uri %s', err.code, uri);
313
- if (err.code === 'ERR_NON_2XX_3XX_RESPONSE') {
314
- const code = err.response.statusCode;
315
- debug('error code %s', code);
316
- if (code === _core.HTTP_STATUS.NOT_FOUND) {
317
- throw _core.errorUtils.getNotFound(_core.API_ERROR.NOT_PACKAGE_UPLINK);
318
- }
319
- if (!(code >= _core.HTTP_STATUS.OK && code < _core.HTTP_STATUS.MULTIPLE_CHOICES)) {
320
- const error = _core.errorUtils.getInternalError(`${_core.API_ERROR.BAD_STATUS_CODE}: ${code}`);
321
- // we need this code to identify outside which status code triggered the error
322
- error.remoteStatus = code;
323
- throw error;
324
- }
325
- } else if (this._isRequestTimeout(err)) {
326
- debug('error code timeout');
327
- throw _core.errorUtils.getServiceUnavailable(_core.API_ERROR.SERVER_TIME_OUT);
490
+ return search;
491
+ }())
492
+ }, {
493
+ key: "addProxyHeaders",
494
+ value: function addProxyHeaders(headers, remoteAddress) {
495
+ // Only submit X-Forwarded-For field if we don't have a proxy selected
496
+ // in the config file.
497
+ //
498
+ // Otherwise misconfigured proxy could return 407
499
+ if (!this.proxy) {
500
+ headers[_core.HEADERS.FORWARDED_FOR] = (headers['x-forwarded-for'] ? headers['x-forwarded-for'] + ', ' : '') + remoteAddress;
328
501
  }
329
- throw err;
330
- }
331
- }
332
502
 
333
- // FIXME: handle stream and retry
334
- fetchTarball(url, overrideOptions) {
335
- debug('fetching url for %s', url);
336
- const options = {
337
- ...this.config,
338
- ...overrideOptions
339
- };
340
- let headers = this.getHeaders(options?.headers);
341
- headers = this.addProxyHeaders(headers, options.remoteAddress);
342
- headers = this.applyUplinkHeaders(headers);
343
- // the following headers cannot be overwritten
344
- if (_lodash.default.isNil(options.etag) === false) {
345
- headers[_core.HEADERS.NONE_MATCH] = options.etag;
346
- headers[_core.HEADERS.ACCEPT] = contentTypeAccept;
503
+ // always attach Via header to avoid loops, even if we're not proxying
504
+ headers['via'] = headers['via'] ? headers['via'] + ', ' : '';
505
+ headers['via'] += '1.1 ' + this.server_id + ' (Verdaccio)';
506
+ return headers;
347
507
  }
348
- const method = 'GET';
349
- // const uri = this.config.url + `/${encode(name)}`;
350
- debug('request uri for %s', url);
351
- const readStream = _gotCjs.default.stream(url, {
352
- headers,
353
- method,
354
- agent: this.agent,
355
- // FIXME: this should be taken from construtor as priority
356
- retry: this.retry ?? options?.retry,
357
- timeout: this.timeout
358
- }).on('request', () => {
359
- this.last_request_time = Date.now();
360
- });
361
- return readStream;
362
- }
363
508
 
364
- /**
365
- * Perform a stream search.
366
- * @param {*} options request options
367
- * @return {Stream}
368
- */
369
- async search({
370
- url,
371
- abort,
372
- retry
373
- }) {
374
- try {
375
- // Incoming URL is relative ie /-/v1/search...
376
- const uri = new _nodeUrl.URL(url, this.url).href;
377
- this.logger.http({
378
- uri,
379
- uplink: this.uplinkName
380
- }, 'search request to uplink @{uplink} - @{uri}');
381
- debug('searching on %o', uri);
382
- const response = (0, _gotCjs.default)(uri, {
383
- signal: abort ? abort.signal : {},
384
- agent: this.agent,
385
- timeout: this.timeout,
386
- retry: retry ?? this.retry
387
- });
388
- const res = await response.text();
389
- const total = JSON.parse(res).total;
390
- debug('number of packages found: %o', total);
391
- const streamSearch = new _nodeStream.PassThrough({
392
- objectMode: true
393
- });
394
- const streamResponse = _nodeStream.Readable.from(res);
395
- // objects is one of the properties on the body, it ignores date and total
396
- streamResponse.pipe(_JSONStream.default.parse('objects')).pipe(streamSearch, {
397
- end: true
398
- });
399
- return streamSearch;
400
- } catch (err) {
401
- debug('search error %s', err);
402
- if (err.response.statusCode === 409) {
403
- throw _core.errorUtils.getInternalError(`bad status code ${err.response.statusCode} from uplink`);
404
- }
405
- this.logger.error({
406
- errorMessage: err?.message,
407
- name: this.uplinkName
408
- }, 'proxy uplink @{name} search error: @{errorMessage}');
409
- throw err;
410
- }
411
- }
412
- addProxyHeaders(headers, remoteAddress) {
413
- // Only submit X-Forwarded-For field if we don't have a proxy selected
414
- // in the config file.
415
- //
416
- // Otherwise misconfigured proxy could return 407
417
- if (!this.proxy) {
418
- headers[_core.HEADERS.FORWARDED_FOR] = (headers['x-forwarded-for'] ? headers['x-forwarded-for'] + ', ' : '') + remoteAddress;
509
+ /**
510
+ * If the request failure.
511
+ * @return {boolean}
512
+ * @private
513
+ */
514
+ }, {
515
+ key: "_ifRequestFailure",
516
+ value: function _ifRequestFailure() {
517
+ return this.failed_requests >= this.max_fails && Math.abs(Date.now() - this.last_request_time) < this.fail_timeout;
419
518
  }
420
519
 
421
- // always attach Via header to avoid loops, even if we're not proxying
422
- headers['via'] = headers['via'] ? headers['via'] + ', ' : '';
423
- headers['via'] += '1.1 ' + this.server_id + ' (Verdaccio)';
424
- return headers;
425
- }
426
-
427
- /**
428
- * If the request failure.
429
- * @return {boolean}
430
- * @private
431
- */
432
- _ifRequestFailure() {
433
- return this.failed_requests >= this.max_fails && Math.abs(Date.now() - this.last_request_time) < this.fail_timeout;
434
- }
435
-
436
- /**
437
- * Check if the request timed out (network or http errors).
438
- * @param {RequestError} err
439
- * @return {boolean}
440
- */
441
- _isRequestTimeout(err) {
442
- const code = err?.response?.statusCode;
443
- return err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT' || err.code === 'ECONNRESET' || code === _core.HTTP_STATUS.REQUEST_TIMEOUT || code === _core.HTTP_STATUS.BAD_GATEWAY || code === _core.HTTP_STATUS.SERVICE_UNAVAILABLE || code === _core.HTTP_STATUS.GATEWAY_TIMEOUT;
444
- }
520
+ /**
521
+ * Check if the request timed out (network or http errors).
522
+ * @param {RequestError} err
523
+ * @return {boolean}
524
+ */
525
+ }, {
526
+ key: "_isRequestTimeout",
527
+ value: function _isRequestTimeout(err) {
528
+ var _err$response;
529
+ var code = err === null || err === void 0 || (_err$response = err.response) === null || _err$response === void 0 ? void 0 : _err$response.statusCode;
530
+ return err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT' || err.code === 'ECONNRESET' || code === _core.HTTP_STATUS.REQUEST_TIMEOUT || code === _core.HTTP_STATUS.BAD_GATEWAY || code === _core.HTTP_STATUS.SERVICE_UNAVAILABLE || code === _core.HTTP_STATUS.GATEWAY_TIMEOUT;
531
+ }
445
532
 
446
- /**
447
- * Set up a proxy.
448
- * @param {*} hostname
449
- * @param {*} config
450
- * @param {*} mainconfig
451
- * @param {*} isHTTPS
452
- */
453
- _setupProxy(hostname, config, mainconfig, isHTTPS) {
454
- let noProxyList;
455
- const proxy_key = isHTTPS ? 'https_proxy' : 'http_proxy';
456
- debug('looking for %o', proxy_key);
533
+ /**
534
+ * Set up a proxy.
535
+ * @param {*} hostname
536
+ * @param {*} config
537
+ * @param {*} mainconfig
538
+ * @param {*} isHTTPS
539
+ */
540
+ }, {
541
+ key: "_setupProxy",
542
+ value: function _setupProxy(hostname, config, mainconfig, isHTTPS) {
543
+ var noProxyList;
544
+ var proxy_key = isHTTPS ? 'https_proxy' : 'http_proxy';
545
+ debug('looking for %o', proxy_key);
457
546
 
458
- // get http_proxy and no_proxy configs
459
- if (proxy_key in config) {
460
- this.proxy = config[proxy_key];
461
- debug('found %o in uplink config', this.proxy);
462
- } else if (proxy_key in mainconfig) {
463
- this.proxy = mainconfig[proxy_key];
464
- debug('found %o in main config', this.proxy);
465
- }
466
- if ('no_proxy' in config) {
467
- noProxyList = config.no_proxy;
468
- } else if ('no_proxy' in mainconfig) {
469
- noProxyList = mainconfig.no_proxy;
470
- }
547
+ // get http_proxy and no_proxy configs
548
+ if (proxy_key in config) {
549
+ this.proxy = config[proxy_key];
550
+ debug('found %o in uplink config', this.proxy);
551
+ } else if (proxy_key in mainconfig) {
552
+ this.proxy = mainconfig[proxy_key];
553
+ debug('found %o in main config', this.proxy);
554
+ }
555
+ if ('no_proxy' in config) {
556
+ noProxyList = config.no_proxy;
557
+ } else if ('no_proxy' in mainconfig) {
558
+ noProxyList = mainconfig.no_proxy;
559
+ }
471
560
 
472
- // use wget-like algorithm to determine if proxy shouldn't be used
473
- if (hostname[0] !== '.') {
474
- hostname = '.' + hostname;
475
- }
476
- if (_lodash.default.isString(noProxyList) && noProxyList.length) {
477
- noProxyList = noProxyList.split(',');
478
- }
479
- if (_lodash.default.isArray(noProxyList)) {
480
- for (let i = 0; i < noProxyList.length; i++) {
481
- let noProxyItem = noProxyList[i];
482
- if (noProxyItem[0] !== '.') {
483
- noProxyItem = '.' + noProxyItem;
484
- }
485
- if (hostname.endsWith(noProxyItem)) {
486
- if (this.proxy) {
487
- debug('not using proxy, excluded by @{rule}', noProxyItem);
488
- this.logger.debug({
489
- url: this.url.href,
490
- rule: noProxyItem
491
- }, 'not using proxy for @{url}, excluded by @{rule} rule');
492
- this.proxy = undefined;
561
+ // use wget-like algorithm to determine if proxy shouldn't be used
562
+ if (hostname[0] !== '.') {
563
+ hostname = '.' + hostname;
564
+ }
565
+ if (_lodash["default"].isString(noProxyList) && noProxyList.length) {
566
+ noProxyList = noProxyList.split(',');
567
+ }
568
+ if (_lodash["default"].isArray(noProxyList)) {
569
+ for (var i = 0; i < noProxyList.length; i++) {
570
+ var noProxyItem = noProxyList[i];
571
+ if (noProxyItem[0] !== '.') {
572
+ noProxyItem = '.' + noProxyItem;
573
+ }
574
+ if (hostname.endsWith(noProxyItem)) {
575
+ if (this.proxy) {
576
+ debug('not using proxy, excluded by @{rule}', noProxyItem);
577
+ this.logger.debug({
578
+ url: this.url.href,
579
+ rule: noProxyItem
580
+ }, 'not using proxy for @{url}, excluded by @{rule} rule');
581
+ this.proxy = undefined;
582
+ }
583
+ break;
493
584
  }
494
- break;
495
585
  }
496
586
  }
587
+ if (typeof this.proxy === 'string') {
588
+ debug('using proxy @{proxy} for @{url}', this.proxy, this.url.href);
589
+ this.logger.debug({
590
+ url: this.url.href,
591
+ proxy: this.proxy
592
+ }, 'using proxy @{proxy} for @{url}');
593
+ }
497
594
  }
498
- if (typeof this.proxy === 'string') {
499
- debug('using proxy @{proxy} for @{url}', this.proxy, this.url.href);
500
- this.logger.debug({
501
- url: this.url.href,
502
- proxy: this.proxy
503
- }, 'using proxy @{proxy} for @{url}');
504
- }
505
- }
506
- }
507
- exports.ProxyStorage = ProxyStorage;
595
+ }]);
596
+ }();
508
597
  //# sourceMappingURL=proxy.js.map