@verdaccio/proxy 6.0.0-6-next.20 → 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.
package/build/proxy.js ADDED
@@ -0,0 +1,565 @@
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 _got = _interopRequireDefault(require("got"));
13
+
14
+ var _lodash = _interopRequireDefault(require("lodash"));
15
+
16
+ var _stream = require("stream");
17
+
18
+ var _undici = require("undici");
19
+
20
+ var _url = require("url");
21
+
22
+ var _core = require("@verdaccio/core");
23
+
24
+ var _utils = require("@verdaccio/utils");
25
+
26
+ var _agent = _interopRequireDefault(require("./agent"));
27
+
28
+ var _proxyUtils = require("./proxy-utils");
29
+
30
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
+
32
+ const LoggerApi = require('@verdaccio/logger');
33
+
34
+ const debug = (0, _debug.default)('verdaccio:proxy');
35
+
36
+ const encode = function (thing) {
37
+ return encodeURIComponent(thing).replace(/^%40/, '@');
38
+ };
39
+
40
+ const jsonContentType = _core.HEADERS.JSON;
41
+ const contentTypeAccept = `${jsonContentType};`;
42
+ /**
43
+ * Just a helper (`config[key] || default` doesn't work because of zeroes)
44
+ */
45
+
46
+ const setConfig = (config, key, def) => {
47
+ return _lodash.default.isNil(config[key]) === false ? config[key] : def;
48
+ };
49
+
50
+ /**
51
+ * Implements Storage interface
52
+ * (same for storage.js, local-storage.js, up-storage.js)
53
+ */
54
+ class ProxyStorage {
55
+ // FIXME: upname is assigned to each instance
56
+ // @ts-ignore
57
+ // @ts-ignore
58
+ constructor(config, mainConfig, agent) {
59
+ this.config = config;
60
+ this.failed_requests = 0;
61
+ this.userAgent = mainConfig.user_agent;
62
+ this.ca = config.ca;
63
+ this.logger = LoggerApi.logger.child({
64
+ sub: 'out'
65
+ });
66
+ this.server_id = mainConfig.server_id;
67
+ this.agent_options = setConfig(this.config, 'agent_options', {
68
+ keepAlive: true,
69
+ maxSockets: 40,
70
+ maxFreeSockets: 10
71
+ });
72
+ this.url = new _url.URL(this.config.url);
73
+ const isHTTPS = this.url.protocol === 'https:';
74
+
75
+ this._setupProxy(this.url.hostname, config, mainConfig, isHTTPS);
76
+
77
+ this.agent = agent ?? this.getAgent();
78
+ this.config.url = this.config.url.replace(/\/$/, '');
79
+
80
+ if (this.config.timeout && Number(this.config.timeout) >= 1000) {
81
+ 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'));
82
+ } // a bunch of different configurable timers
83
+
84
+
85
+ this.maxage = (0, _proxyUtils.parseInterval)(setConfig(this.config, 'maxage', '2m')); // https://github.com/sindresorhus/got/blob/main/documentation/6-timeout.md
86
+
87
+ this.timeout = (0, _proxyUtils.parseInterval)(setConfig(this.config, 'timeout', '30s'));
88
+ this.max_fails = Number(setConfig(this.config, 'max_fails', this.config.max_fails ?? 2));
89
+ this.fail_timeout = (0, _proxyUtils.parseInterval)(setConfig(this.config, 'fail_timeout', '5m'));
90
+ this.strict_ssl = Boolean(setConfig(this.config, 'strict_ssl', true));
91
+ this.retry = {
92
+ limit: this.max_fails ?? 2
93
+ };
94
+ }
95
+
96
+ getAgent() {
97
+ if (!this.agent) {
98
+ // TODO: the config.ca (certificates) is not yet injected here
99
+ const agentInstance = new _agent.default(this.config.url, this.proxy, this.agent_options);
100
+ return agentInstance.get();
101
+ } else {
102
+ return this.agent;
103
+ }
104
+ }
105
+
106
+ getHeadersNext(headers = {}) {
107
+ const accept = _core.HEADERS.ACCEPT;
108
+ const acceptEncoding = _core.HEADERS.ACCEPT_ENCODING;
109
+ const userAgent = _core.HEADERS.USER_AGENT;
110
+ headers[accept] = headers[accept] || contentTypeAccept;
111
+ headers[acceptEncoding] = headers[acceptEncoding] || 'gzip'; // registry.npmjs.org will only return search result if user-agent include string 'npm'
112
+
113
+ headers[userAgent] = headers[userAgent] || `npm (${this.userAgent})`;
114
+ return this.setAuthNext(headers);
115
+ }
116
+ /**
117
+ * Validate configuration auth and assign Header authorization
118
+ * @param {Object} headers
119
+ * @return {Object}
120
+ * @private
121
+ */
122
+
123
+
124
+ setAuthNext(headers) {
125
+ const {
126
+ auth
127
+ } = this.config;
128
+
129
+ if (typeof auth === 'undefined' || typeof headers[_core.HEADERS.AUTHORIZATION] === 'string') {
130
+ return headers;
131
+ }
132
+
133
+ if (_lodash.default.isObject(auth) === false && _lodash.default.isObject(auth.token) === false) {
134
+ this._throwErrorAuth('Auth invalid');
135
+ } // get NPM_TOKEN http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules
136
+ // or get other variable export in env
137
+ // https://github.com/verdaccio/verdaccio/releases/tag/v2.5.0
138
+
139
+
140
+ let token;
141
+ const tokenConf = auth;
142
+
143
+ if (_lodash.default.isNil(tokenConf.token) === false && _lodash.default.isString(tokenConf.token)) {
144
+ token = tokenConf.token;
145
+ } else if (_lodash.default.isNil(tokenConf.token_env) === false) {
146
+ if (typeof tokenConf.token_env === 'string') {
147
+ token = process.env[tokenConf.token_env];
148
+ } else if (typeof tokenConf.token_env === 'boolean' && tokenConf.token_env) {
149
+ token = process.env.NPM_TOKEN;
150
+ } else {
151
+ this.logger.error(_core.constants.ERROR_CODE.token_required);
152
+
153
+ this._throwErrorAuth(_core.constants.ERROR_CODE.token_required);
154
+ }
155
+ } else {
156
+ token = process.env.NPM_TOKEN;
157
+ }
158
+
159
+ if (typeof token === 'undefined') {
160
+ this._throwErrorAuth(_core.constants.ERROR_CODE.token_required);
161
+ } // define type Auth allow basic and bearer
162
+
163
+
164
+ const type = tokenConf.type || _core.TOKEN_BASIC;
165
+
166
+ this._setHeaderAuthorization(headers, type, token);
167
+
168
+ return headers;
169
+ }
170
+ /**
171
+ * @param {string} message
172
+ * @throws {Error}
173
+ * @private
174
+ */
175
+
176
+
177
+ _throwErrorAuth(message) {
178
+ this.logger.error(message);
179
+ throw new Error(message);
180
+ }
181
+ /**
182
+ * Assign Header authorization with type authentication
183
+ * @param {Object} headers
184
+ * @param {string} type
185
+ * @param {string} token
186
+ * @private
187
+ */
188
+
189
+
190
+ _setHeaderAuthorization(headers, type, token) {
191
+ const _type = type.toLowerCase();
192
+
193
+ if (_type !== _core.TOKEN_BEARER.toLowerCase() && _type !== _core.TOKEN_BASIC.toLowerCase()) {
194
+ this._throwErrorAuth(`Auth type '${_type}' not allowed`);
195
+ }
196
+
197
+ type = _lodash.default.upperFirst(type);
198
+ headers[_core.HEADERS.AUTHORIZATION] = (0, _utils.buildToken)(type, token);
199
+ }
200
+ /**
201
+ * It will add or override specified headers from config file.
202
+ *
203
+ * Eg:
204
+ *
205
+ * uplinks:
206
+ npmjs:
207
+ url: https://registry.npmjs.org/
208
+ headers:
209
+ Accept: "application/vnd.npm.install-v2+json; q=1.0"
210
+ verdaccio-staging:
211
+ url: https://mycompany.com/npm
212
+ headers:
213
+ Accept: "application/json"
214
+ authorization: "Basic YourBase64EncodedCredentials=="
215
+ * @param {Object} headers
216
+ * @private
217
+ * @deprecated use applyUplinkHeaders
218
+ */
219
+
220
+
221
+ _overrideWithUpLinkConfLocaligHeaders(headers) {
222
+ if (!this.config.headers) {
223
+ return headers;
224
+ } // add/override headers specified in the config
225
+
226
+ /* eslint guard-for-in: 0 */
227
+
228
+
229
+ for (const key in this.config.headers) {
230
+ headers[key] = this.config.headers[key];
231
+ }
232
+ }
233
+
234
+ applyUplinkHeaders(headers) {
235
+ if (!this.config.headers) {
236
+ return headers;
237
+ } // add/override headers specified in the config
238
+
239
+ /* eslint guard-for-in: 0 */
240
+
241
+
242
+ for (const key in this.config.headers) {
243
+ headers[key] = this.config.headers[key];
244
+ }
245
+
246
+ return headers;
247
+ }
248
+
249
+ async getRemoteMetadataNext(name, options) {
250
+ if (this._ifRequestFailure()) {
251
+ throw _core.errorUtils.getInternalError(_core.API_ERROR.UPLINK_OFFLINE);
252
+ } // FUTURE: allow mix headers that comes from the client
253
+
254
+
255
+ debug('get metadata for %s', name);
256
+ let headers = this.getHeadersNext(options === null || options === void 0 ? void 0 : options.headers);
257
+ headers = this.addProxyHeaders(headers, options.remoteAddress);
258
+ headers = this.applyUplinkHeaders(headers); // the following headers cannot be overwritten
259
+
260
+ if (_lodash.default.isNil(options.etag) === false) {
261
+ headers[_core.HEADERS.NONE_MATCH] = options.etag;
262
+ headers[_core.HEADERS.ACCEPT] = contentTypeAccept;
263
+ }
264
+
265
+ const method = options.method || 'GET';
266
+ const uri = this.config.url + `/${encode(name)}`;
267
+ debug('request uri for %s retry %s', uri);
268
+ let response;
269
+ let responseLength = 0;
270
+
271
+ try {
272
+ var _response;
273
+
274
+ const retry = (options === null || options === void 0 ? void 0 : options.retry) ?? this.retry;
275
+ debug('retry times %s for %s', retry, uri);
276
+ response = await (0, _got.default)(uri, {
277
+ headers,
278
+ responseType: 'json',
279
+ method,
280
+ agent: this.agent,
281
+ retry,
282
+ // @ts-ignore
283
+ timeout: {
284
+ request: (options === null || options === void 0 ? void 0 : options.timeout) ?? this.timeout
285
+ },
286
+ hooks: {
287
+ afterResponse: [afterResponse => {
288
+ const code = afterResponse.statusCode;
289
+ debug('code response %s', code);
290
+
291
+ if (code >= _core.HTTP_STATUS.OK && code < _core.HTTP_STATUS.MULTIPLE_CHOICES) {
292
+ if (this.failed_requests >= this.max_fails) {
293
+ this.failed_requests = 0;
294
+ this.logger.warn({
295
+ host: this.url.host
296
+ }, 'host @{host} is now online');
297
+ }
298
+ }
299
+
300
+ return afterResponse;
301
+ }],
302
+ beforeRetry: [// FUTURE: got 12.0.0, the option arg should be removed
303
+ (_options, error, count) => {
304
+ this.failed_requests = count ?? 0;
305
+ this.logger.info({
306
+ request: {
307
+ method: method,
308
+ url: uri
309
+ },
310
+ error: error.message,
311
+ retryCount: this.failed_requests
312
+ }, "retry @{retryCount} req: '@{request.method} @{request.url}'");
313
+
314
+ if (this.failed_requests >= this.max_fails) {
315
+ this.logger.warn({
316
+ host: this.url.host
317
+ }, 'host @{host} is now offline');
318
+ }
319
+ }]
320
+ }
321
+ }).on('request', () => {
322
+ this.last_request_time = Date.now();
323
+ }).on('response', eventResponse => {
324
+ const message = "@{!status}, req: '@{request.method} @{request.url}' (streaming)";
325
+ this.logger.http({
326
+ request: {
327
+ method: method,
328
+ url: uri
329
+ },
330
+ status: _lodash.default.isNull(eventResponse) === false ? eventResponse.statusCode : 'ERR'
331
+ }, message);
332
+ }).on('downloadProgress', progress => {
333
+ if (progress.total) {
334
+ debug('responseLength %s', progress.total);
335
+ responseLength = progress.total;
336
+ }
337
+ });
338
+ const etag = response.headers.etag;
339
+ const data = response.body; // not modified status (304) registry does not return any payload
340
+ // it is handled as an error
341
+
342
+ if (((_response = response) === null || _response === void 0 ? void 0 : _response.statusCode) === _core.HTTP_STATUS.NOT_MODIFIED) {
343
+ throw _core.errorUtils.getCode(_core.HTTP_STATUS.NOT_MODIFIED, _core.API_ERROR.NOT_MODIFIED_NO_DATA);
344
+ }
345
+
346
+ debug('uri %s success', uri);
347
+ const message = "@{!status}, req: '@{request.method} @{request.url}'";
348
+ this.logger.http({
349
+ // if error is null/false change this to undefined so it wont log
350
+ request: {
351
+ method: method,
352
+ url: uri
353
+ },
354
+ status: response.statusCode,
355
+ bytes: {
356
+ in: options !== null && options !== void 0 && options.json ? JSON.stringify(options === null || options === void 0 ? void 0 : options.json).length : 0,
357
+ out: responseLength || 0
358
+ }
359
+ }, message);
360
+ return [data, etag];
361
+ } catch (err) {
362
+ debug('uri %s fail', uri);
363
+
364
+ if (err.code === 'ERR_NON_2XX_3XX_RESPONSE') {
365
+ const code = err.response.statusCode;
366
+
367
+ if (code === _core.HTTP_STATUS.NOT_FOUND) {
368
+ throw _core.errorUtils.getNotFound(_core.errorUtils.API_ERROR.NOT_PACKAGE_UPLINK);
369
+ }
370
+
371
+ if (!(code >= _core.HTTP_STATUS.OK && code < _core.HTTP_STATUS.MULTIPLE_CHOICES)) {
372
+ const error = _core.errorUtils.getInternalError(`${_core.errorUtils.API_ERROR.BAD_STATUS_CODE}: ${code}`); // we need this code to identify outside which status code triggered the error
373
+
374
+
375
+ error.remoteStatus = code;
376
+ throw error;
377
+ }
378
+ }
379
+
380
+ throw err;
381
+ }
382
+ } // FIXME: handle stream and retry
383
+
384
+
385
+ fetchTarballNext(url, overrideOptions) {
386
+ debug('fetching url for %s', url);
387
+ const options = { ...this.config,
388
+ ...overrideOptions
389
+ };
390
+ let headers = this.getHeadersNext(options === null || options === void 0 ? void 0 : options.headers);
391
+ headers = this.addProxyHeaders(headers, options.remoteAddress);
392
+ headers = this.applyUplinkHeaders(headers); // the following headers cannot be overwritten
393
+
394
+ if (_lodash.default.isNil(options.etag) === false) {
395
+ headers[_core.HEADERS.NONE_MATCH] = options.etag;
396
+ headers[_core.HEADERS.ACCEPT] = contentTypeAccept;
397
+ }
398
+
399
+ const method = 'GET'; // const uri = this.config.url + `/${encode(name)}`;
400
+
401
+ debug('request uri for %s', url);
402
+
403
+ const readStream = _got.default.stream(url, {
404
+ headers,
405
+ method,
406
+ agent: this.agent,
407
+ // FIXME: this should be taken from construtor as priority
408
+ retry: this.retry ?? (options === null || options === void 0 ? void 0 : options.retry),
409
+ timeout: this.timeout
410
+ }).on('request', () => {
411
+ this.last_request_time = Date.now();
412
+ });
413
+
414
+ return readStream;
415
+ }
416
+ /**
417
+ * Perform a stream search.
418
+ * @param {*} options request options
419
+ * @return {Stream}
420
+ */
421
+
422
+
423
+ async search({
424
+ url,
425
+ abort
426
+ }) {
427
+ debug('search url %o', url);
428
+ let response;
429
+
430
+ try {
431
+ const fullURL = new _url.URL(`${this.url}${url}`); // FIXME: a better way to remove duplicate slashes?
432
+
433
+ const uri = fullURL.href.replace(/([^:]\/)\/+/g, '$1');
434
+ this.logger.http({
435
+ uri,
436
+ uplink: this.upname
437
+ }, 'search request to uplink @{uplink} - @{uri}');
438
+ response = await (0, _undici.fetch)(uri, {
439
+ method: 'GET',
440
+ // FUTURE: whitelist domains what we are sending not need it headers, security check
441
+ // headers: new Headers({
442
+ // ...headers,
443
+ // connection: 'keep-alive',
444
+ // }),
445
+ signal: abort === null || abort === void 0 ? void 0 : abort.signal
446
+ });
447
+ debug('response.status %o', response.status);
448
+
449
+ if (response.status >= _core.HTTP_STATUS.BAD_REQUEST) {
450
+ throw _core.errorUtils.getInternalError(`bad status code ${response.status} from uplink`);
451
+ }
452
+
453
+ const streamSearch = new _stream.PassThrough({
454
+ objectMode: true
455
+ });
456
+ const res = await response.text();
457
+
458
+ const streamResponse = _stream.Readable.from(res); // objects is one of the properties on the body, it ignores date and total
459
+
460
+
461
+ streamResponse.pipe(_JSONStream.default.parse('objects')).pipe(streamSearch, {
462
+ end: true
463
+ });
464
+ return streamSearch;
465
+ } catch (err) {
466
+ this.logger.error({
467
+ errorMessage: err === null || err === void 0 ? void 0 : err.message,
468
+ name: this.upname
469
+ }, 'proxy uplink @{name} search error: @{errorMessage}');
470
+ throw err;
471
+ }
472
+ }
473
+
474
+ addProxyHeaders(headers, remoteAddress) {
475
+ // Only submit X-Forwarded-For field if we don't have a proxy selected
476
+ // in the config file.
477
+ //
478
+ // Otherwise misconfigured proxy could return 407
479
+ if (!this.proxy) {
480
+ headers[_core.HEADERS.FORWARDED_FOR] = (headers['x-forwarded-for'] ? headers['x-forwarded-for'] + ', ' : '') + remoteAddress;
481
+ } // always attach Via header to avoid loops, even if we're not proxying
482
+
483
+
484
+ headers['via'] = headers['via'] ? headers['via'] + ', ' : '';
485
+ headers['via'] += '1.1 ' + this.server_id + ' (Verdaccio)';
486
+ return headers;
487
+ }
488
+ /**
489
+ * If the request failure.
490
+ * @return {boolean}
491
+ * @private
492
+ */
493
+
494
+
495
+ _ifRequestFailure() {
496
+ return this.failed_requests >= this.max_fails && Math.abs(Date.now() - this.last_request_time) < this.fail_timeout;
497
+ }
498
+ /**
499
+ * Set up a proxy.
500
+ * @param {*} hostname
501
+ * @param {*} config
502
+ * @param {*} mainconfig
503
+ * @param {*} isHTTPS
504
+ */
505
+
506
+
507
+ _setupProxy(hostname, config, mainconfig, isHTTPS) {
508
+ let noProxyList;
509
+ const proxy_key = isHTTPS ? 'https_proxy' : 'http_proxy'; // get http_proxy and no_proxy configs
510
+
511
+ if (proxy_key in config) {
512
+ this.proxy = config[proxy_key];
513
+ } else if (proxy_key in mainconfig) {
514
+ this.proxy = mainconfig[proxy_key];
515
+ }
516
+
517
+ if ('no_proxy' in config) {
518
+ noProxyList = config.no_proxy;
519
+ } else if ('no_proxy' in mainconfig) {
520
+ noProxyList = mainconfig.no_proxy;
521
+ } // use wget-like algorithm to determine if proxy shouldn't be used
522
+
523
+
524
+ if (hostname[0] !== '.') {
525
+ hostname = '.' + hostname;
526
+ }
527
+
528
+ if (_lodash.default.isString(noProxyList) && noProxyList.length) {
529
+ noProxyList = noProxyList.split(',');
530
+ }
531
+
532
+ if (_lodash.default.isArray(noProxyList)) {
533
+ for (let i = 0; i < noProxyList.length; i++) {
534
+ let noProxyItem = noProxyList[i];
535
+
536
+ if (noProxyItem[0] !== '.') {
537
+ noProxyItem = '.' + noProxyItem;
538
+ }
539
+
540
+ if (hostname.endsWith(noProxyItem)) {
541
+ if (this.proxy) {
542
+ this.logger.debug({
543
+ url: this.url.href,
544
+ rule: noProxyItem
545
+ }, 'not using proxy for @{url}, excluded by @{rule} rule');
546
+ this.proxy = undefined;
547
+ }
548
+
549
+ break;
550
+ }
551
+ }
552
+ }
553
+
554
+ if (typeof this.proxy === 'string') {
555
+ this.logger.debug({
556
+ url: this.url.href,
557
+ proxy: this.proxy
558
+ }, 'using proxy @{proxy} for @{url}');
559
+ }
560
+ }
561
+
562
+ }
563
+
564
+ exports.ProxyStorage = ProxyStorage;
565
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","names":["LoggerApi","require","debug","buildDebug","encode","thing","encodeURIComponent","replace","jsonContentType","HEADERS","JSON","contentTypeAccept","setConfig","config","key","def","_","isNil","ProxyStorage","constructor","mainConfig","agent","failed_requests","userAgent","user_agent","ca","logger","child","sub","server_id","agent_options","keepAlive","maxSockets","maxFreeSockets","url","URL","isHTTPS","protocol","_setupProxy","hostname","getAgent","timeout","Number","warn","join","maxage","parseInterval","max_fails","fail_timeout","strict_ssl","Boolean","retry","limit","agentInstance","CustomAgents","proxy","get","getHeadersNext","headers","accept","ACCEPT","acceptEncoding","ACCEPT_ENCODING","USER_AGENT","setAuthNext","auth","AUTHORIZATION","isObject","token","_throwErrorAuth","tokenConf","isString","token_env","process","env","NPM_TOKEN","error","constants","ERROR_CODE","token_required","type","TOKEN_BASIC","_setHeaderAuthorization","message","Error","_type","toLowerCase","TOKEN_BEARER","upperFirst","buildToken","_overrideWithUpLinkConfLocaligHeaders","applyUplinkHeaders","getRemoteMetadataNext","name","options","_ifRequestFailure","errorUtils","getInternalError","API_ERROR","UPLINK_OFFLINE","addProxyHeaders","remoteAddress","etag","NONE_MATCH","method","uri","response","responseLength","got","responseType","request","hooks","afterResponse","code","statusCode","HTTP_STATUS","OK","MULTIPLE_CHOICES","host","beforeRetry","_options","count","info","retryCount","on","last_request_time","Date","now","eventResponse","http","status","isNull","progress","total","data","body","NOT_MODIFIED","getCode","NOT_MODIFIED_NO_DATA","bytes","in","json","stringify","length","out","err","NOT_FOUND","getNotFound","NOT_PACKAGE_UPLINK","BAD_STATUS_CODE","remoteStatus","fetchTarballNext","overrideOptions","readStream","stream","search","abort","fullURL","href","uplink","upname","undiciFetch","signal","BAD_REQUEST","streamSearch","PassThrough","objectMode","res","text","streamResponse","Readable","from","pipe","JSONStream","parse","end","errorMessage","FORWARDED_FOR","Math","abs","mainconfig","noProxyList","proxy_key","no_proxy","split","isArray","i","noProxyItem","endsWith","rule","undefined"],"sources":["../src/proxy.ts"],"sourcesContent":["import JSONStream from 'JSONStream';\nimport buildDebug from 'debug';\nimport got, { RequiredRetryOptions, Headers as gotHeaders } from 'got';\nimport type { Agents, Options } from 'got';\nimport _ from 'lodash';\nimport Stream, { PassThrough, Readable } from 'stream';\nimport { Headers, fetch as undiciFetch } from 'undici';\nimport { URL } from 'url';\n\nimport {\n API_ERROR,\n HEADERS,\n HTTP_STATUS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n constants,\n errorUtils,\n searchUtils,\n} from '@verdaccio/core';\nimport { Manifest } from '@verdaccio/types';\nimport { Config, Logger, UpLinkConf } from '@verdaccio/types';\nimport { buildToken } from '@verdaccio/utils';\n\nimport CustomAgents, { AgentOptionsConf } from './agent';\nimport { parseInterval } from './proxy-utils';\n\nconst LoggerApi = require('@verdaccio/logger');\n\nconst debug = buildDebug('verdaccio:proxy');\n\nconst encode = function (thing): string {\n return encodeURIComponent(thing).replace(/^%40/, '@');\n};\n\nconst jsonContentType = HEADERS.JSON;\nconst contentTypeAccept = `${jsonContentType};`;\n\n/**\n * Just a helper (`config[key] || default` doesn't work because of zeroes)\n */\nconst setConfig = (config: UpLinkConfLocal, key: string, def): string => {\n return _.isNil(config[key]) === false ? config[key] : def;\n};\n\nexport type UpLinkConfLocal = UpLinkConf & {\n no_proxy?: string;\n};\n\nexport interface ProxyList {\n [key: string]: IProxy;\n}\n\nexport type ProxySearchParams = {\n headers?: Headers;\n url: string;\n query?: searchUtils.SearchQuery;\n abort: AbortController;\n};\nexport interface IProxy {\n config: UpLinkConfLocal;\n failed_requests: number;\n userAgent: string;\n ca?: string | void;\n logger: Logger;\n server_id: string;\n url: URL;\n maxage: number;\n timeout: number;\n max_fails: number;\n fail_timeout: number;\n upname: string;\n search(options: ProxySearchParams): Promise<Stream.Readable>;\n getRemoteMetadataNext(name: string, options: ISyncUplinksOptions): Promise<[Manifest, string]>;\n fetchTarballNext(\n url: string,\n options: Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'>\n ): PassThrough;\n}\n\n// this type is need it by storage\nexport { Options as FetchOptions };\n\nexport interface ISyncUplinksOptions extends Options {\n uplinksLook?: boolean;\n etag?: string;\n remoteAddress?: string;\n}\n\n/**\n * Implements Storage interface\n * (same for storage.js, local-storage.js, up-storage.js)\n */\nclass ProxyStorage implements IProxy {\n public config: UpLinkConfLocal;\n public failed_requests: number;\n public userAgent: string;\n public ca: string | void;\n public logger: Logger;\n public server_id: string;\n public url: URL;\n public maxage: number;\n public timeout: number;\n public max_fails: number;\n public fail_timeout: number;\n public agent_options: AgentOptionsConf;\n // FIXME: upname is assigned to each instance\n // @ts-ignore\n public upname: string;\n public proxy: string | undefined;\n private agent: Agents;\n // @ts-ignore\n public last_request_time: number | null;\n public strict_ssl: boolean;\n private retry: Partial<RequiredRetryOptions> | number;\n\n public constructor(config: UpLinkConfLocal, mainConfig: Config, agent?: Agents) {\n this.config = config;\n this.failed_requests = 0;\n this.userAgent = mainConfig.user_agent;\n this.ca = config.ca;\n this.logger = LoggerApi.logger.child({ sub: 'out' });\n this.server_id = mainConfig.server_id;\n this.agent_options = setConfig(this.config, 'agent_options', {\n keepAlive: true,\n maxSockets: 40,\n maxFreeSockets: 10,\n }) as AgentOptionsConf;\n this.url = new URL(this.config.url);\n const isHTTPS = this.url.protocol === 'https:';\n this._setupProxy(this.url.hostname, config, mainConfig, isHTTPS);\n this.agent = agent ?? this.getAgent();\n this.config.url = this.config.url.replace(/\\/$/, '');\n\n if (this.config.timeout && Number(this.config.timeout) >= 1000) {\n this.logger.warn(\n [\n 'Too big timeout value: ' + this.config.timeout,\n 'We changed time format to nginx-like one',\n '(see http://nginx.org/en/docs/syntax.html)',\n 'so please update your config accordingly',\n ].join('\\n')\n );\n }\n\n // a bunch of different configurable timers\n this.maxage = parseInterval(setConfig(this.config, 'maxage', '2m'));\n // https://github.com/sindresorhus/got/blob/main/documentation/6-timeout.md\n this.timeout = parseInterval(setConfig(this.config, 'timeout', '30s'));\n this.max_fails = Number(setConfig(this.config, 'max_fails', this.config.max_fails ?? 2));\n this.fail_timeout = parseInterval(setConfig(this.config, 'fail_timeout', '5m'));\n this.strict_ssl = Boolean(setConfig(this.config, 'strict_ssl', true));\n this.retry = { limit: this.max_fails ?? 2 };\n }\n\n private getAgent() {\n if (!this.agent) {\n // TODO: the config.ca (certificates) is not yet injected here\n const agentInstance = new CustomAgents(this.config.url, this.proxy, this.agent_options);\n return agentInstance.get();\n } else {\n return this.agent;\n }\n }\n\n public getHeadersNext(headers = {}): gotHeaders {\n const accept = HEADERS.ACCEPT;\n const acceptEncoding = HEADERS.ACCEPT_ENCODING;\n const userAgent = HEADERS.USER_AGENT;\n\n headers[accept] = headers[accept] || contentTypeAccept;\n headers[acceptEncoding] = headers[acceptEncoding] || 'gzip';\n // registry.npmjs.org will only return search result if user-agent include string 'npm'\n headers[userAgent] = headers[userAgent] || `npm (${this.userAgent})`;\n return this.setAuthNext(headers);\n }\n\n /**\n * Validate configuration auth and assign Header authorization\n * @param {Object} headers\n * @return {Object}\n * @private\n */\n private setAuthNext(headers: gotHeaders): gotHeaders {\n const { auth } = this.config;\n if (typeof auth === 'undefined' || typeof headers[HEADERS.AUTHORIZATION] === 'string') {\n return headers;\n }\n\n if (_.isObject(auth) === false && _.isObject(auth.token) === false) {\n this._throwErrorAuth('Auth invalid');\n }\n\n // get NPM_TOKEN http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules\n // or get other variable export in env\n // https://github.com/verdaccio/verdaccio/releases/tag/v2.5.0\n let token: any;\n const tokenConf: any = auth;\n if (_.isNil(tokenConf.token) === false && _.isString(tokenConf.token)) {\n token = tokenConf.token;\n } else if (_.isNil(tokenConf.token_env) === false) {\n if (typeof tokenConf.token_env === 'string') {\n token = process.env[tokenConf.token_env];\n } else if (typeof tokenConf.token_env === 'boolean' && tokenConf.token_env) {\n token = process.env.NPM_TOKEN;\n } else {\n this.logger.error(constants.ERROR_CODE.token_required);\n this._throwErrorAuth(constants.ERROR_CODE.token_required);\n }\n } else {\n token = process.env.NPM_TOKEN;\n }\n\n if (typeof token === 'undefined') {\n this._throwErrorAuth(constants.ERROR_CODE.token_required);\n }\n\n // define type Auth allow basic and bearer\n const type = tokenConf.type || TOKEN_BASIC;\n this._setHeaderAuthorization(headers, type, token);\n\n return headers;\n }\n\n /**\n * @param {string} message\n * @throws {Error}\n * @private\n */\n private _throwErrorAuth(message: string): Error {\n this.logger.error(message);\n throw new Error(message);\n }\n\n /**\n * Assign Header authorization with type authentication\n * @param {Object} headers\n * @param {string} type\n * @param {string} token\n * @private\n */\n private _setHeaderAuthorization(headers: any, type: string, token: any): void {\n const _type: string = type.toLowerCase();\n\n if (_type !== TOKEN_BEARER.toLowerCase() && _type !== TOKEN_BASIC.toLowerCase()) {\n this._throwErrorAuth(`Auth type '${_type}' not allowed`);\n }\n\n type = _.upperFirst(type);\n headers[HEADERS.AUTHORIZATION] = buildToken(type, token);\n }\n\n /**\n * It will add or override specified headers from config file.\n *\n * Eg:\n *\n * uplinks:\n npmjs:\n url: https://registry.npmjs.org/\n headers:\n Accept: \"application/vnd.npm.install-v2+json; q=1.0\"\n verdaccio-staging:\n url: https://mycompany.com/npm\n headers:\n Accept: \"application/json\"\n authorization: \"Basic YourBase64EncodedCredentials==\"\n\n * @param {Object} headers\n * @private\n * @deprecated use applyUplinkHeaders\n */\n private _overrideWithUpLinkConfLocaligHeaders(headers: Headers): any {\n if (!this.config.headers) {\n return headers;\n }\n\n // add/override headers specified in the config\n /* eslint guard-for-in: 0 */\n for (const key in this.config.headers) {\n headers[key] = this.config.headers[key];\n }\n }\n\n private applyUplinkHeaders(headers: gotHeaders): gotHeaders {\n if (!this.config.headers) {\n return headers;\n }\n\n // add/override headers specified in the config\n /* eslint guard-for-in: 0 */\n for (const key in this.config.headers) {\n headers[key] = this.config.headers[key];\n }\n return headers;\n }\n\n public async getRemoteMetadataNext(\n name: string,\n options: ISyncUplinksOptions\n ): Promise<[Manifest, string]> {\n if (this._ifRequestFailure()) {\n throw errorUtils.getInternalError(API_ERROR.UPLINK_OFFLINE);\n }\n\n // FUTURE: allow mix headers that comes from the client\n debug('get metadata for %s', name);\n let headers = this.getHeadersNext(options?.headers);\n headers = this.addProxyHeaders(headers, options.remoteAddress);\n headers = this.applyUplinkHeaders(headers);\n // the following headers cannot be overwritten\n if (_.isNil(options.etag) === false) {\n headers[HEADERS.NONE_MATCH] = options.etag;\n headers[HEADERS.ACCEPT] = contentTypeAccept;\n }\n const method = options.method || 'GET';\n const uri = this.config.url + `/${encode(name)}`;\n debug('request uri for %s retry %s', uri);\n let response;\n let responseLength = 0;\n try {\n const retry = options?.retry ?? this.retry;\n debug('retry times %s for %s', retry, uri);\n response = await got(uri, {\n headers,\n responseType: 'json',\n method,\n agent: this.agent,\n retry,\n // @ts-ignore\n timeout: { request: options?.timeout ?? this.timeout },\n hooks: {\n afterResponse: [\n (afterResponse) => {\n const code = afterResponse.statusCode;\n debug('code response %s', code);\n if (code >= HTTP_STATUS.OK && code < HTTP_STATUS.MULTIPLE_CHOICES) {\n if (this.failed_requests >= this.max_fails) {\n this.failed_requests = 0;\n this.logger.warn(\n {\n host: this.url.host,\n },\n 'host @{host} is now online'\n );\n }\n }\n\n return afterResponse;\n },\n ],\n beforeRetry: [\n // FUTURE: got 12.0.0, the option arg should be removed\n (_options, error: any, count) => {\n this.failed_requests = count ?? 0;\n this.logger.info(\n {\n request: {\n method: method,\n url: uri,\n },\n error: error.message,\n retryCount: this.failed_requests,\n },\n \"retry @{retryCount} req: '@{request.method} @{request.url}'\"\n );\n if (this.failed_requests >= this.max_fails) {\n this.logger.warn(\n {\n host: this.url.host,\n },\n 'host @{host} is now offline'\n );\n }\n },\n ],\n },\n })\n .on('request', () => {\n this.last_request_time = Date.now();\n })\n .on('response', (eventResponse) => {\n const message = \"@{!status}, req: '@{request.method} @{request.url}' (streaming)\";\n this.logger.http(\n {\n request: {\n method: method,\n url: uri,\n },\n status: _.isNull(eventResponse) === false ? eventResponse.statusCode : 'ERR',\n },\n message\n );\n })\n .on('downloadProgress', (progress) => {\n if (progress.total) {\n debug('responseLength %s', progress.total);\n responseLength = progress.total;\n }\n });\n const etag = response.headers.etag as string;\n const data = response.body;\n\n // not modified status (304) registry does not return any payload\n // it is handled as an error\n if (response?.statusCode === HTTP_STATUS.NOT_MODIFIED) {\n throw errorUtils.getCode(HTTP_STATUS.NOT_MODIFIED, API_ERROR.NOT_MODIFIED_NO_DATA);\n }\n\n debug('uri %s success', uri);\n const message = \"@{!status}, req: '@{request.method} @{request.url}'\";\n this.logger.http(\n {\n // if error is null/false change this to undefined so it wont log\n request: { method: method, url: uri },\n status: response.statusCode,\n bytes: {\n in: options?.json ? JSON.stringify(options?.json).length : 0,\n out: responseLength || 0,\n },\n },\n message\n );\n return [data, etag];\n } catch (err: any) {\n debug('uri %s fail', uri);\n if (err.code === 'ERR_NON_2XX_3XX_RESPONSE') {\n const code = err.response.statusCode;\n if (code === HTTP_STATUS.NOT_FOUND) {\n throw errorUtils.getNotFound(errorUtils.API_ERROR.NOT_PACKAGE_UPLINK);\n }\n\n if (!(code >= HTTP_STATUS.OK && code < HTTP_STATUS.MULTIPLE_CHOICES)) {\n const error = errorUtils.getInternalError(\n `${errorUtils.API_ERROR.BAD_STATUS_CODE}: ${code}`\n );\n // we need this code to identify outside which status code triggered the error\n error.remoteStatus = code;\n throw error;\n }\n }\n throw err;\n }\n }\n\n // FIXME: handle stream and retry\n public fetchTarballNext(\n url: string,\n overrideOptions: Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'>\n ): any {\n debug('fetching url for %s', url);\n const options = { ...this.config, ...overrideOptions };\n let headers = this.getHeadersNext(options?.headers);\n headers = this.addProxyHeaders(headers, options.remoteAddress);\n headers = this.applyUplinkHeaders(headers);\n // the following headers cannot be overwritten\n if (_.isNil(options.etag) === false) {\n headers[HEADERS.NONE_MATCH] = options.etag;\n headers[HEADERS.ACCEPT] = contentTypeAccept;\n }\n const method = 'GET';\n // const uri = this.config.url + `/${encode(name)}`;\n debug('request uri for %s', url);\n\n const readStream = got\n .stream(url, {\n headers,\n method,\n agent: this.agent,\n // FIXME: this should be taken from construtor as priority\n retry: this.retry ?? options?.retry,\n timeout: this.timeout,\n })\n .on('request', () => {\n this.last_request_time = Date.now();\n });\n\n return readStream;\n }\n\n /**\n * Perform a stream search.\n * @param {*} options request options\n * @return {Stream}\n */\n public async search({ url, abort }: ProxySearchParams): Promise<Stream.Readable> {\n debug('search url %o', url);\n\n let response;\n try {\n const fullURL = new URL(`${this.url}${url}`);\n // FIXME: a better way to remove duplicate slashes?\n const uri = fullURL.href.replace(/([^:]\\/)\\/+/g, '$1');\n this.logger.http({ uri, uplink: this.upname }, 'search request to uplink @{uplink} - @{uri}');\n response = await undiciFetch(uri, {\n method: 'GET',\n // FUTURE: whitelist domains what we are sending not need it headers, security check\n // headers: new Headers({\n // ...headers,\n // connection: 'keep-alive',\n // }),\n signal: abort?.signal,\n });\n debug('response.status %o', response.status);\n\n if (response.status >= HTTP_STATUS.BAD_REQUEST) {\n throw errorUtils.getInternalError(`bad status code ${response.status} from uplink`);\n }\n\n const streamSearch = new PassThrough({ objectMode: true });\n const res = await response.text();\n const streamResponse = Readable.from(res);\n // objects is one of the properties on the body, it ignores date and total\n streamResponse.pipe(JSONStream.parse('objects')).pipe(streamSearch, { end: true });\n return streamSearch;\n } catch (err: any) {\n this.logger.error(\n { errorMessage: err?.message, name: this.upname },\n 'proxy uplink @{name} search error: @{errorMessage}'\n );\n throw err;\n }\n }\n\n private addProxyHeaders(headers: gotHeaders, remoteAddress?: string): gotHeaders {\n // Only submit X-Forwarded-For field if we don't have a proxy selected\n // in the config file.\n //\n // Otherwise misconfigured proxy could return 407\n if (!this.proxy) {\n headers[HEADERS.FORWARDED_FOR] =\n (headers['x-forwarded-for'] ? headers['x-forwarded-for'] + ', ' : '') + remoteAddress;\n }\n\n // always attach Via header to avoid loops, even if we're not proxying\n headers['via'] = headers['via'] ? headers['via'] + ', ' : '';\n headers['via'] += '1.1 ' + this.server_id + ' (Verdaccio)';\n\n return headers;\n }\n\n /**\n * If the request failure.\n * @return {boolean}\n * @private\n */\n private _ifRequestFailure(): boolean {\n return (\n this.failed_requests >= this.max_fails &&\n Math.abs(Date.now() - (this.last_request_time as number)) < this.fail_timeout\n );\n }\n\n /**\n * Set up a proxy.\n * @param {*} hostname\n * @param {*} config\n * @param {*} mainconfig\n * @param {*} isHTTPS\n */\n private _setupProxy(\n hostname: string,\n config: UpLinkConfLocal,\n mainconfig: Config,\n isHTTPS: boolean\n ): void {\n let noProxyList;\n const proxy_key: string = isHTTPS ? 'https_proxy' : 'http_proxy';\n\n // get http_proxy and no_proxy configs\n if (proxy_key in config) {\n this.proxy = config[proxy_key];\n } else if (proxy_key in mainconfig) {\n this.proxy = mainconfig[proxy_key];\n }\n if ('no_proxy' in config) {\n noProxyList = config.no_proxy;\n } else if ('no_proxy' in mainconfig) {\n noProxyList = mainconfig.no_proxy;\n }\n\n // use wget-like algorithm to determine if proxy shouldn't be used\n if (hostname[0] !== '.') {\n hostname = '.' + hostname;\n }\n\n if (_.isString(noProxyList) && noProxyList.length) {\n noProxyList = noProxyList.split(',');\n }\n\n if (_.isArray(noProxyList)) {\n for (let i = 0; i < noProxyList.length; i++) {\n let noProxyItem = noProxyList[i];\n if (noProxyItem[0] !== '.') {\n noProxyItem = '.' + noProxyItem;\n }\n if (hostname.endsWith(noProxyItem)) {\n if (this.proxy) {\n this.logger.debug(\n { url: this.url.href, rule: noProxyItem },\n 'not using proxy for @{url}, excluded by @{rule} rule'\n );\n this.proxy = undefined;\n }\n break;\n }\n }\n }\n\n if (typeof this.proxy === 'string') {\n this.logger.debug(\n { url: this.url.href, proxy: this.proxy },\n 'using proxy @{proxy} for @{url}'\n );\n }\n }\n}\n\nexport { ProxyStorage };\n"],"mappings":"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"}
package/jest.config.js CHANGED
@@ -1,13 +1,12 @@
1
1
  const config = require('../../jest/config');
2
2
 
3
3
  module.exports = Object.assign({}, config, {
4
- collectCoverage: true,
5
4
  coverageThreshold: {
6
5
  global: {
7
- branches: 80,
8
- functions: 90,
9
- lines: 92,
10
- statements: 90,
6
+ branches: 79,
7
+ functions: 94,
8
+ lines: 87,
9
+ statements: 87,
11
10
  },
12
11
  },
13
12
  });