@verdaccio/proxy 9.0.0-next-9.36 → 9.0.0-next-9.37

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 +1 @@
1
- {"version":3,"file":"agent.js","names":[],"sources":["../src/agent.ts"],"sourcesContent":["import type { Agents } from 'got';\nimport { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';\nimport { Agent as HttpAgent } from 'node:http';\nimport { Agent as HttpsAgent } from 'node:https';\nimport { URL } from 'node:url';\n\nimport type { AgentOptionsConf } from '@verdaccio/types';\n\nclass CustomAgents {\n private url: string;\n private proxy: string | undefined;\n private agentOptions: AgentOptionsConf;\n private agent: Agents;\n public constructor(url: string, proxy: string | undefined, agentOptions: AgentOptionsConf) {\n this.proxy = proxy;\n this.url = url;\n this.agentOptions = agentOptions;\n // Type of agent depends on the protocol of the server URL (no on the proxy)\n // See https://www.npmjs.com/package/hpagent\n const { protocol } = new URL(this.url);\n this.agent = this.getAgent(protocol);\n }\n\n public get() {\n return this.agent;\n }\n\n private getAgent(protocol: string): Agents {\n const isHTTPS = protocol === 'https:';\n if (this.proxy) {\n const options = {\n proxy: this.proxy,\n ...this.agentOptions,\n };\n // use hpagent\n return isHTTPS\n ? { https: new HttpsProxyAgent(options) }\n : { http: new HttpProxyAgent(options) };\n } else {\n // use native http/https agent\n return isHTTPS\n ? { https: new HttpsAgent(this.agentOptions) }\n : { http: new HttpAgent(this.agentOptions) };\n }\n }\n}\n\nexport default CustomAgents;\n"],"mappings":";;;;;AAQA,IAAM,eAAN,MAAmB;CACjB;CACA;CACA;CACA;CACA,YAAmB,KAAa,OAA2B,cAAgC;EACzF,KAAK,QAAQ;EACb,KAAK,MAAM;EACX,KAAK,eAAe;EAGpB,MAAM,EAAE,aAAa,IAAI,SAAA,IAAI,KAAK,GAAG;EACrC,KAAK,QAAQ,KAAK,SAAS,QAAQ;CACrC;CAEA,MAAa;EACX,OAAO,KAAK;CACd;CAEA,SAAiB,UAA0B;EACzC,MAAM,UAAU,aAAa;EAC7B,IAAI,KAAK,OAAO;GACd,MAAM,UAAU;IACd,OAAO,KAAK;IACZ,GAAG,KAAK;GACV;GAEA,OAAO,UACH,EAAE,OAAO,IAAI,QAAA,gBAAgB,OAAO,EAAE,IACtC,EAAE,MAAM,IAAI,QAAA,eAAe,OAAO,EAAE;EAC1C,OAEE,OAAO,UACH,EAAE,OAAO,IAAI,WAAA,MAAW,KAAK,YAAY,EAAE,IAC3C,EAAE,MAAM,IAAI,UAAA,MAAU,KAAK,YAAY,EAAE;CAEjD;AACF"}
1
+ {"version":3,"file":"agent.js","names":["URL","HttpsProxyAgent","HttpProxyAgent","HttpsAgent","HttpAgent"],"sources":["../src/agent.ts"],"sourcesContent":["import type { Agents } from 'got';\nimport { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';\nimport { Agent as HttpAgent } from 'node:http';\nimport { Agent as HttpsAgent } from 'node:https';\nimport { URL } from 'node:url';\n\nimport type { AgentOptionsConf } from '@verdaccio/types';\n\nclass CustomAgents {\n private url: string;\n private proxy: string | undefined;\n private agentOptions: AgentOptionsConf;\n private agent: Agents;\n public constructor(url: string, proxy: string | undefined, agentOptions: AgentOptionsConf) {\n this.proxy = proxy;\n this.url = url;\n this.agentOptions = agentOptions;\n // Type of agent depends on the protocol of the server URL (no on the proxy)\n // See https://www.npmjs.com/package/hpagent\n const { protocol } = new URL(this.url);\n this.agent = this.getAgent(protocol);\n }\n\n public get() {\n return this.agent;\n }\n\n private getAgent(protocol: string): Agents {\n const isHTTPS = protocol === 'https:';\n if (this.proxy) {\n const options = {\n proxy: this.proxy,\n ...this.agentOptions,\n };\n // use hpagent\n return isHTTPS\n ? { https: new HttpsProxyAgent(options) }\n : { http: new HttpProxyAgent(options) };\n } else {\n // use native http/https agent\n return isHTTPS\n ? { https: new HttpsAgent(this.agentOptions) }\n : { http: new HttpAgent(this.agentOptions) };\n }\n }\n}\n\nexport default CustomAgents;\n"],"mappings":";;;;;AAQA,IAAM,eAAN,MAAmB;CACjB;CACA;CACA;CACA;CACA,YAAmB,KAAa,OAA2B,cAAgC;EACzF,KAAK,QAAQ;EACb,KAAK,MAAM;EACX,KAAK,eAAe;EAGpB,MAAM,EAAE,aAAa,IAAIA,SAAAA,IAAI,KAAK,GAAG;EACrC,KAAK,QAAQ,KAAK,SAAS,QAAQ;CACrC;CAEA,MAAa;EACX,OAAO,KAAK;CACd;CAEA,SAAiB,UAA0B;EACzC,MAAM,UAAU,aAAa;EAC7B,IAAI,KAAK,OAAO;GACd,MAAM,UAAU;IACd,OAAO,KAAK;IACZ,GAAG,KAAK;GACV;GAEA,OAAO,UACH,EAAE,OAAO,IAAIC,QAAAA,gBAAgB,OAAO,EAAE,IACtC,EAAE,MAAM,IAAIC,QAAAA,eAAe,OAAO,EAAE;EAC1C,OAEE,OAAO,UACH,EAAE,OAAO,IAAIC,WAAAA,MAAW,KAAK,YAAY,EAAE,IAC3C,EAAE,MAAM,IAAIC,UAAAA,MAAU,KAAK,YAAY,EAAE;CAEjD;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent.mjs","names":[],"sources":["../src/agent.ts"],"sourcesContent":["import type { Agents } from 'got';\nimport { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';\nimport { Agent as HttpAgent } from 'node:http';\nimport { Agent as HttpsAgent } from 'node:https';\nimport { URL } from 'node:url';\n\nimport type { AgentOptionsConf } from '@verdaccio/types';\n\nclass CustomAgents {\n private url: string;\n private proxy: string | undefined;\n private agentOptions: AgentOptionsConf;\n private agent: Agents;\n public constructor(url: string, proxy: string | undefined, agentOptions: AgentOptionsConf) {\n this.proxy = proxy;\n this.url = url;\n this.agentOptions = agentOptions;\n // Type of agent depends on the protocol of the server URL (no on the proxy)\n // See https://www.npmjs.com/package/hpagent\n const { protocol } = new URL(this.url);\n this.agent = this.getAgent(protocol);\n }\n\n public get() {\n return this.agent;\n }\n\n private getAgent(protocol: string): Agents {\n const isHTTPS = protocol === 'https:';\n if (this.proxy) {\n const options = {\n proxy: this.proxy,\n ...this.agentOptions,\n };\n // use hpagent\n return isHTTPS\n ? { https: new HttpsProxyAgent(options) }\n : { http: new HttpProxyAgent(options) };\n } else {\n // use native http/https agent\n return isHTTPS\n ? { https: new HttpsAgent(this.agentOptions) }\n : { http: new HttpAgent(this.agentOptions) };\n }\n }\n}\n\nexport default CustomAgents;\n"],"mappings":";;;;;AAQA,IAAM,eAAN,MAAmB;CACjB;CACA;CACA;CACA;CACA,YAAmB,KAAa,OAA2B,cAAgC;EACzF,KAAK,QAAQ;EACb,KAAK,MAAM;EACX,KAAK,eAAe;EAGpB,MAAM,EAAE,aAAa,IAAI,IAAI,KAAK,GAAG;EACrC,KAAK,QAAQ,KAAK,SAAS,QAAQ;CACrC;CAEA,MAAa;EACX,OAAO,KAAK;CACd;CAEA,SAAiB,UAA0B;EACzC,MAAM,UAAU,aAAa;EAC7B,IAAI,KAAK,OAAO;GACd,MAAM,UAAU;IACd,OAAO,KAAK;IACZ,GAAG,KAAK;GACV;GAEA,OAAO,UACH,EAAE,OAAO,IAAI,gBAAgB,OAAO,EAAE,IACtC,EAAE,MAAM,IAAI,eAAe,OAAO,EAAE;EAC1C,OAEE,OAAO,UACH,EAAE,OAAO,IAAI,QAAW,KAAK,YAAY,EAAE,IAC3C,EAAE,MAAM,IAAI,MAAU,KAAK,YAAY,EAAE;CAEjD;AACF"}
1
+ {"version":3,"file":"agent.mjs","names":["HttpsAgent","HttpAgent"],"sources":["../src/agent.ts"],"sourcesContent":["import type { Agents } from 'got';\nimport { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';\nimport { Agent as HttpAgent } from 'node:http';\nimport { Agent as HttpsAgent } from 'node:https';\nimport { URL } from 'node:url';\n\nimport type { AgentOptionsConf } from '@verdaccio/types';\n\nclass CustomAgents {\n private url: string;\n private proxy: string | undefined;\n private agentOptions: AgentOptionsConf;\n private agent: Agents;\n public constructor(url: string, proxy: string | undefined, agentOptions: AgentOptionsConf) {\n this.proxy = proxy;\n this.url = url;\n this.agentOptions = agentOptions;\n // Type of agent depends on the protocol of the server URL (no on the proxy)\n // See https://www.npmjs.com/package/hpagent\n const { protocol } = new URL(this.url);\n this.agent = this.getAgent(protocol);\n }\n\n public get() {\n return this.agent;\n }\n\n private getAgent(protocol: string): Agents {\n const isHTTPS = protocol === 'https:';\n if (this.proxy) {\n const options = {\n proxy: this.proxy,\n ...this.agentOptions,\n };\n // use hpagent\n return isHTTPS\n ? { https: new HttpsProxyAgent(options) }\n : { http: new HttpProxyAgent(options) };\n } else {\n // use native http/https agent\n return isHTTPS\n ? { https: new HttpsAgent(this.agentOptions) }\n : { http: new HttpAgent(this.agentOptions) };\n }\n }\n}\n\nexport default CustomAgents;\n"],"mappings":";;;;;AAQA,IAAM,eAAN,MAAmB;CACjB;CACA;CACA;CACA;CACA,YAAmB,KAAa,OAA2B,cAAgC;EACzF,KAAK,QAAQ;EACb,KAAK,MAAM;EACX,KAAK,eAAe;EAGpB,MAAM,EAAE,aAAa,IAAI,IAAI,KAAK,GAAG;EACrC,KAAK,QAAQ,KAAK,SAAS,QAAQ;CACrC;CAEA,MAAa;EACX,OAAO,KAAK;CACd;CAEA,SAAiB,UAA0B;EACzC,MAAM,UAAU,aAAa;EAC7B,IAAI,KAAK,OAAO;GACd,MAAM,UAAU;IACd,OAAO,KAAK;IACZ,GAAG,KAAK;GACV;GAEA,OAAO,UACH,EAAE,OAAO,IAAI,gBAAgB,OAAO,EAAE,IACtC,EAAE,MAAM,IAAI,eAAe,OAAO,EAAE;EAC1C,OAEE,OAAO,UACH,EAAE,OAAO,IAAIA,QAAW,KAAK,YAAY,EAAE,IAC3C,EAAE,MAAM,IAAIC,MAAU,KAAK,YAAY,EAAE;CAEjD;AACF"}
package/build/index.js CHANGED
@@ -5,7 +5,12 @@ Object.defineProperties(exports, {
5
5
  const require_proxy = require("./proxy.js");
6
6
  const require_uplink_util = require("./uplink-util.js");
7
7
  let got = require("got");
8
- exports.FetchOptions = got.Options;
8
+ Object.defineProperty(exports, "FetchOptions", {
9
+ enumerable: true,
10
+ get: function() {
11
+ return got.Options;
12
+ }
13
+ });
9
14
  exports.ProxyStorage = require_proxy.ProxyStorage;
10
15
  exports.setupUpLinks = require_uplink_util.setupUpLinks;
11
16
  exports.updateVersionsHiddenUpLinkNext = require_uplink_util.updateVersionsHiddenUpLinkNext;
package/build/proxy.d.ts CHANGED
@@ -112,6 +112,7 @@ declare class ProxyStorage implements IProxy {
112
112
  */
113
113
  private applyUplinkHeaders;
114
114
  getRemoteMetadata(name: string, options: Partial<ISyncUplinksOptions>): Promise<[Manifest, string]>;
115
+ private logUplinkResponse;
115
116
  fetchTarball(url: string, overrideOptions: Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'> & {
116
117
  throwHttpErrors?: boolean;
117
118
  }): any;
package/build/proxy.js CHANGED
@@ -227,13 +227,7 @@ var ProxyStorage = class {
227
227
  }).on("request", () => {
228
228
  this.last_request_time = Date.now();
229
229
  }).on("response", (eventResponse) => {
230
- this.logger.http({
231
- request: {
232
- method,
233
- url: uri
234
- },
235
- status: eventResponse !== null ? eventResponse.statusCode : "ERR"
236
- }, "@{!status}, req: '@{request.method} @{request.url}' (streaming)");
230
+ this.logUplinkResponse(method, uri, eventResponse);
237
231
  }).on("downloadProgress", (progress) => {
238
232
  if (progress.total) {
239
233
  debug$1("responseLength %s", progress.total);
@@ -265,6 +259,7 @@ var ProxyStorage = class {
265
259
  if (err.code === "ERR_NON_2XX_3XX_RESPONSE") {
266
260
  const code = err.response.statusCode;
267
261
  debug$1("error code %s", code);
262
+ this.logUplinkResponse(method, uri, err.response);
268
263
  if (code === _verdaccio_core.HTTP_STATUS.NOT_FOUND) throw _verdaccio_core.errorUtils.getNotFound(_verdaccio_core.API_ERROR.NOT_PACKAGE_UPLINK);
269
264
  if (!(code >= _verdaccio_core.HTTP_STATUS.OK && code < _verdaccio_core.HTTP_STATUS.MULTIPLE_CHOICES)) {
270
265
  const error = _verdaccio_core.errorUtils.getInternalError(`${_verdaccio_core.API_ERROR.BAD_STATUS_CODE}: ${code}`);
@@ -278,6 +273,15 @@ var ProxyStorage = class {
278
273
  throw err;
279
274
  }
280
275
  }
276
+ logUplinkResponse(method, uri, response) {
277
+ this.logger.http({
278
+ request: {
279
+ method,
280
+ url: uri
281
+ },
282
+ status: response !== null ? response.statusCode : "ERR"
283
+ }, "@{!status}, req: '@{request.method} @{request.url}' (streaming)");
284
+ }
281
285
  fetchTarball(url, overrideOptions) {
282
286
  debug$1("fetching url for %s", url);
283
287
  const options = {
@@ -427,7 +431,12 @@ var ProxyStorage = class {
427
431
  }
428
432
  };
429
433
  //#endregion
430
- exports.FetchOptions = got.Options;
434
+ Object.defineProperty(exports, "FetchOptions", {
435
+ enumerable: true,
436
+ get: function() {
437
+ return got.Options;
438
+ }
439
+ });
431
440
  exports.ProxyStorage = ProxyStorage;
432
441
 
433
442
  //# sourceMappingURL=proxy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","names":[],"sources":["../src/proxy.ts"],"sourcesContent":["import JSONStream from 'JSONStream';\nimport buildDebug from 'debug';\nimport type { Agents, Delays, RequestError, RetryOptions, Headers as gotHeaders } from 'got';\nimport got, { Options } from 'got';\nimport { isNil, isObject } from 'lodash-es';\nimport type Stream from 'node:stream';\nimport { PassThrough, Readable } from 'node:stream';\nimport { URL } from 'node:url';\n\nimport type { searchUtils } from '@verdaccio/core';\nimport {\n API_ERROR,\n HEADERS,\n HTTP_STATUS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n authUtils,\n constants,\n errorUtils,\n} from '@verdaccio/core';\nimport type { AgentOptionsConf, Config, Logger, Manifest, UpLinkConf } from '@verdaccio/types';\n\nimport CustomAgents from './agent';\nimport { parseInterval } from './proxy-utils';\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 url: string;\n abort: AbortController;\n query?: searchUtils.SearchQuery;\n headers?: Headers;\n retry?: Partial<RetryOptions>;\n onSearchPage?: (total: number | undefined) => void;\n};\nexport interface IProxy {\n uplinkName: string;\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: Delays;\n max_fails: number;\n fail_timeout: number;\n search(options: ProxySearchParams): Promise<Stream.Readable>;\n getRemoteMetadata(\n name: string,\n options: Partial<ISyncUplinksOptions>\n ): Promise<[Manifest, string]>;\n fetchTarball(\n url: string,\n options: Partial<Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'>> & {\n throwHttpErrors?: boolean;\n }\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 uplinkName: string;\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: Delays;\n public max_fails: number;\n public fail_timeout: number;\n public agent_options: AgentOptionsConf;\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<RetryOptions>;\n\n public constructor(\n uplinkName: string,\n config: UpLinkConfLocal,\n mainConfig: Config,\n logger: Logger,\n agent?: Agents\n ) {\n this.uplinkName = uplinkName;\n this.config = config;\n this.failed_requests = 0;\n this.userAgent = mainConfig.user_agent ?? 'hidden';\n this.ca = config.ca;\n this.logger = logger;\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 = {\n request: parseInterval(setConfig(this.config, 'timeout', '30s')),\n };\n debug('set timeout %s', this.timeout);\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 // `max_fails` is the circuit-breaker threshold (failed requests before the\n // uplink is considered offline) and must not drive the per-request retry\n // count — otherwise a high max_fails multiplies every uplink timeout by\n // that value. Retries have their own `retry` setting (default matches got).\n const retryConfig = setConfig(this.config, 'retry', 2);\n this.retry =\n typeof retryConfig === 'object' && retryConfig !== null\n ? (retryConfig as Partial<RetryOptions>)\n : { limit: Number(retryConfig) };\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 getHeaders(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 as any).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 && typeof tokenConf.token === 'string') {\n debug('use token from config');\n token = tokenConf.token;\n } else if (isNil(tokenConf.token_env) === false) {\n if (typeof tokenConf.token_env === 'string') {\n debug('use token from env %o', tokenConf.token_env);\n token = process.env[tokenConf.token_env];\n } else if (typeof tokenConf.token_env === 'boolean' && tokenConf.token_env) {\n debug('use token from env NPM_TOKEN');\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 debug('use token from env NPM_TOKEN');\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 debug('token type %o', type);\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 headers[HEADERS.AUTHORIZATION] = authUtils.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 */\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 getRemoteMetadata(\n name: string,\n options: Partial<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('getting metadata for package %s', name);\n let headers = this.getHeaders(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('set retry limit is %s', this.retry.limit);\n let response;\n let responseLength = 0;\n try {\n const retry = options?.retry ?? this.retry;\n debug('retry initial count %s', retry);\n response = await got(uri, {\n headers,\n responseType: 'json',\n method,\n agent: this.agent,\n retry,\n timeout: this.timeout,\n hooks: {\n afterResponse: [\n (afterResponse) => {\n const code = afterResponse.statusCode;\n debug('after response code is %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 (error: RequestError, count: number) => {\n debug('retry %s count: %s', uri, 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<any>('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: eventResponse !== null ? 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 with the original 304 status preserved\n if (response?.statusCode === HTTP_STATUS.NOT_MODIFIED) {\n const err = errorUtils.getNotFound(API_ERROR.NOT_MODIFIED_NO_DATA);\n err.code = HTTP_STATUS.NOT_MODIFIED;\n throw err;\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('error %s on uri %s', err.code, uri);\n if (err.code === 'ERR_NON_2XX_3XX_RESPONSE') {\n const code = err.response.statusCode;\n debug('error code %s', code);\n if (code === HTTP_STATUS.NOT_FOUND) {\n throw errorUtils.getNotFound(API_ERROR.NOT_PACKAGE_UPLINK);\n }\n\n if (!(code >= HTTP_STATUS.OK && code < HTTP_STATUS.MULTIPLE_CHOICES)) {\n const error = errorUtils.getInternalError(`${API_ERROR.BAD_STATUS_CODE}: ${code}`);\n // we need this code to identify outside which status code triggered the error\n error.remoteStatus = code;\n throw error;\n }\n } else if (this._isRequestTimeout(err)) {\n debug('error code timeout');\n throw errorUtils.getServiceUnavailable(API_ERROR.SERVER_TIME_OUT);\n }\n throw err;\n }\n }\n\n // FIXME: handle stream and retry\n public fetchTarball(\n url: string,\n overrideOptions: Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'> & {\n throwHttpErrors?: boolean;\n }\n ): any {\n debug('fetching url for %s', url);\n const options = { ...this.config, ...overrideOptions };\n let headers = this.getHeaders(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 // surface the outgoing tarball request so devops can observe which host a\n // tarball is fetched from (an autogenerated proxy shows as verdaccio-<pkg>)\n this.logger.http({ url, uplink: this.uplinkName }, 'fetching tarball from @{uplink} - @{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 ...(typeof overrideOptions.throwHttpErrors === 'boolean'\n ? { throwHttpErrors: overrideOptions.throwHttpErrors }\n : {}),\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({\n url,\n abort,\n retry,\n onSearchPage,\n }: ProxySearchParams): Promise<Stream.Readable> {\n try {\n const uri = this.buildUri(url);\n const headers = this.applyUplinkHeaders(this.getHeaders());\n this.logger.http(\n { uri, uplink: this.uplinkName },\n 'search request to uplink @{uplink} - @{uri}'\n );\n debug('searching on %o', uri);\n const response = got(uri, {\n headers,\n signal: abort ? abort.signal : undefined,\n agent: this.agent,\n timeout: this.timeout,\n retry: retry ?? this.retry,\n });\n\n const res = await (response.text() as unknown as Promise<string>);\n const total = JSON.parse(res).total;\n onSearchPage?.(Number.isSafeInteger(total) && total >= 0 ? total : undefined);\n debug('number of packages found: %o', total);\n const streamSearch = new PassThrough({ objectMode: true });\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 if (onSearchPage) {\n if (!abort?.signal.aborted) {\n this.logger.error(\n { errorMessage: err?.message, name: this.uplinkName },\n 'proxy uplink @{name} search error: @{errorMessage}'\n );\n }\n throw abort?.signal.aborted\n ? abort.signal.reason\n : errorUtils.getServiceUnavailable('uplink search failed');\n }\n debug('search error %s', err);\n if (err?.response?.statusCode === HTTP_STATUS.CONFLICT) {\n throw errorUtils.getInternalError(`bad status code ${err.response.statusCode} from uplink`);\n }\n if (!abort?.signal.aborted) {\n this.logger.error(\n { errorMessage: err?.message, name: this.uplinkName },\n 'proxy uplink @{name} search error: @{errorMessage}'\n );\n }\n throw err;\n }\n }\n\n private buildUri(path: string): string {\n const base = new URL(this.url);\n base.pathname = `${base.pathname.replace(/\\/+$/, '')}/`;\n return new URL(path.replace(/^\\/+/, ''), base).href;\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 * Check if the request timed out (network or http errors).\n * @param {RequestError} err\n * @return {boolean}\n */\n private _isRequestTimeout(err: RequestError): boolean {\n const code = err?.response?.statusCode;\n return (\n err.code === 'ETIMEDOUT' ||\n err.code === 'ESOCKETTIMEDOUT' ||\n err.code === 'ECONNRESET' ||\n code === HTTP_STATUS.REQUEST_TIMEOUT ||\n code === HTTP_STATUS.BAD_GATEWAY ||\n code === HTTP_STATUS.SERVICE_UNAVAILABLE ||\n code === HTTP_STATUS.GATEWAY_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 debug('looking for %o', proxy_key);\n\n // get http_proxy and no_proxy configs\n if (proxy_key in config) {\n this.proxy = config[proxy_key];\n debug('found %o in uplink config', this.proxy);\n } else if (proxy_key in mainconfig) {\n this.proxy = mainconfig[proxy_key];\n debug('found %o in main config', this.proxy);\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 (typeof noProxyList === 'string' && noProxyList.length) {\n noProxyList = noProxyList.split(',');\n }\n\n if (Array.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 debug('not using proxy, excluded by @{rule}', noProxyItem);\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 debug('using proxy @{proxy} for @{url}', this.proxy, this.url.href);\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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"}
1
+ {"version":3,"file":"proxy.js","names":["debug","buildDebug","HEADERS","isNil","URL","parseInterval","CustomAgents","isObject","constants","TOKEN_BASIC","TOKEN_BEARER","authUtils","errorUtils","API_ERROR","HTTP_STATUS","PassThrough","Readable"],"sources":["../src/proxy.ts"],"sourcesContent":["import JSONStream from 'JSONStream';\nimport buildDebug from 'debug';\nimport type { Agents, Delays, RequestError, RetryOptions, Headers as gotHeaders } from 'got';\nimport got, { Options } from 'got';\nimport { isNil, isObject } from 'lodash-es';\nimport type Stream from 'node:stream';\nimport { PassThrough, Readable } from 'node:stream';\nimport { URL } from 'node:url';\n\nimport type { searchUtils } from '@verdaccio/core';\nimport {\n API_ERROR,\n HEADERS,\n HTTP_STATUS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n authUtils,\n constants,\n errorUtils,\n} from '@verdaccio/core';\nimport type { AgentOptionsConf, Config, Logger, Manifest, UpLinkConf } from '@verdaccio/types';\n\nimport CustomAgents from './agent';\nimport { parseInterval } from './proxy-utils';\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 url: string;\n abort: AbortController;\n query?: searchUtils.SearchQuery;\n headers?: Headers;\n retry?: Partial<RetryOptions>;\n onSearchPage?: (total: number | undefined) => void;\n};\nexport interface IProxy {\n uplinkName: string;\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: Delays;\n max_fails: number;\n fail_timeout: number;\n search(options: ProxySearchParams): Promise<Stream.Readable>;\n getRemoteMetadata(\n name: string,\n options: Partial<ISyncUplinksOptions>\n ): Promise<[Manifest, string]>;\n fetchTarball(\n url: string,\n options: Partial<Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'>> & {\n throwHttpErrors?: boolean;\n }\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 uplinkName: string;\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: Delays;\n public max_fails: number;\n public fail_timeout: number;\n public agent_options: AgentOptionsConf;\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<RetryOptions>;\n\n public constructor(\n uplinkName: string,\n config: UpLinkConfLocal,\n mainConfig: Config,\n logger: Logger,\n agent?: Agents\n ) {\n this.uplinkName = uplinkName;\n this.config = config;\n this.failed_requests = 0;\n this.userAgent = mainConfig.user_agent ?? 'hidden';\n this.ca = config.ca;\n this.logger = logger;\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 = {\n request: parseInterval(setConfig(this.config, 'timeout', '30s')),\n };\n debug('set timeout %s', this.timeout);\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 // `max_fails` is the circuit-breaker threshold (failed requests before the\n // uplink is considered offline) and must not drive the per-request retry\n // count — otherwise a high max_fails multiplies every uplink timeout by\n // that value. Retries have their own `retry` setting (default matches got).\n const retryConfig = setConfig(this.config, 'retry', 2);\n this.retry =\n typeof retryConfig === 'object' && retryConfig !== null\n ? (retryConfig as Partial<RetryOptions>)\n : { limit: Number(retryConfig) };\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 getHeaders(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 as any).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 && typeof tokenConf.token === 'string') {\n debug('use token from config');\n token = tokenConf.token;\n } else if (isNil(tokenConf.token_env) === false) {\n if (typeof tokenConf.token_env === 'string') {\n debug('use token from env %o', tokenConf.token_env);\n token = process.env[tokenConf.token_env];\n } else if (typeof tokenConf.token_env === 'boolean' && tokenConf.token_env) {\n debug('use token from env NPM_TOKEN');\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 debug('use token from env NPM_TOKEN');\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 debug('token type %o', type);\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 headers[HEADERS.AUTHORIZATION] = authUtils.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 */\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 getRemoteMetadata(\n name: string,\n options: Partial<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('getting metadata for package %s', name);\n let headers = this.getHeaders(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('set retry limit is %s', this.retry.limit);\n let response;\n let responseLength = 0;\n try {\n const retry = options?.retry ?? this.retry;\n debug('retry initial count %s', retry);\n response = await got(uri, {\n headers,\n responseType: 'json',\n method,\n agent: this.agent,\n retry,\n timeout: this.timeout,\n hooks: {\n afterResponse: [\n (afterResponse) => {\n const code = afterResponse.statusCode;\n debug('after response code is %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 (error: RequestError, count: number) => {\n debug('retry %s count: %s', uri, 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<any>('response', (eventResponse) => {\n this.logUplinkResponse(method, uri, eventResponse);\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 with the original 304 status preserved\n if (response?.statusCode === HTTP_STATUS.NOT_MODIFIED) {\n const err = errorUtils.getNotFound(API_ERROR.NOT_MODIFIED_NO_DATA);\n err.code = HTTP_STATUS.NOT_MODIFIED;\n throw err;\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('error %s on uri %s', err.code, uri);\n if (err.code === 'ERR_NON_2XX_3XX_RESPONSE') {\n const code = err.response.statusCode;\n debug('error code %s', code);\n // got only emits `response` for the response the promise resolves with\n this.logUplinkResponse(method, uri, err.response);\n if (code === HTTP_STATUS.NOT_FOUND) {\n throw errorUtils.getNotFound(API_ERROR.NOT_PACKAGE_UPLINK);\n }\n\n if (!(code >= HTTP_STATUS.OK && code < HTTP_STATUS.MULTIPLE_CHOICES)) {\n const error = errorUtils.getInternalError(`${API_ERROR.BAD_STATUS_CODE}: ${code}`);\n // we need this code to identify outside which status code triggered the error\n error.remoteStatus = code;\n throw error;\n }\n } else if (this._isRequestTimeout(err)) {\n debug('error code timeout');\n throw errorUtils.getServiceUnavailable(API_ERROR.SERVER_TIME_OUT);\n }\n throw err;\n }\n }\n\n private logUplinkResponse(method: string, uri: string, response: { statusCode: number } | null) {\n this.logger.http(\n {\n request: { method, url: uri },\n status: response !== null ? response.statusCode : 'ERR',\n },\n \"@{!status}, req: '@{request.method} @{request.url}' (streaming)\"\n );\n }\n\n // FIXME: handle stream and retry\n public fetchTarball(\n url: string,\n overrideOptions: Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'> & {\n throwHttpErrors?: boolean;\n }\n ): any {\n debug('fetching url for %s', url);\n const options = { ...this.config, ...overrideOptions };\n let headers = this.getHeaders(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 // surface the outgoing tarball request so devops can observe which host a\n // tarball is fetched from (an autogenerated proxy shows as verdaccio-<pkg>)\n this.logger.http({ url, uplink: this.uplinkName }, 'fetching tarball from @{uplink} - @{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 ...(typeof overrideOptions.throwHttpErrors === 'boolean'\n ? { throwHttpErrors: overrideOptions.throwHttpErrors }\n : {}),\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({\n url,\n abort,\n retry,\n onSearchPage,\n }: ProxySearchParams): Promise<Stream.Readable> {\n try {\n const uri = this.buildUri(url);\n const headers = this.applyUplinkHeaders(this.getHeaders());\n this.logger.http(\n { uri, uplink: this.uplinkName },\n 'search request to uplink @{uplink} - @{uri}'\n );\n debug('searching on %o', uri);\n const response = got(uri, {\n headers,\n signal: abort ? abort.signal : undefined,\n agent: this.agent,\n timeout: this.timeout,\n retry: retry ?? this.retry,\n });\n\n const res = await (response.text() as unknown as Promise<string>);\n const total = JSON.parse(res).total;\n onSearchPage?.(Number.isSafeInteger(total) && total >= 0 ? total : undefined);\n debug('number of packages found: %o', total);\n const streamSearch = new PassThrough({ objectMode: true });\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 if (onSearchPage) {\n if (!abort?.signal.aborted) {\n this.logger.error(\n { errorMessage: err?.message, name: this.uplinkName },\n 'proxy uplink @{name} search error: @{errorMessage}'\n );\n }\n throw abort?.signal.aborted\n ? abort.signal.reason\n : errorUtils.getServiceUnavailable('uplink search failed');\n }\n debug('search error %s', err);\n if (err?.response?.statusCode === HTTP_STATUS.CONFLICT) {\n throw errorUtils.getInternalError(`bad status code ${err.response.statusCode} from uplink`);\n }\n if (!abort?.signal.aborted) {\n this.logger.error(\n { errorMessage: err?.message, name: this.uplinkName },\n 'proxy uplink @{name} search error: @{errorMessage}'\n );\n }\n throw err;\n }\n }\n\n private buildUri(path: string): string {\n const base = new URL(this.url);\n base.pathname = `${base.pathname.replace(/\\/+$/, '')}/`;\n return new URL(path.replace(/^\\/+/, ''), base).href;\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 * Check if the request timed out (network or http errors).\n * @param {RequestError} err\n * @return {boolean}\n */\n private _isRequestTimeout(err: RequestError): boolean {\n const code = err?.response?.statusCode;\n return (\n err.code === 'ETIMEDOUT' ||\n err.code === 'ESOCKETTIMEDOUT' ||\n err.code === 'ECONNRESET' ||\n code === HTTP_STATUS.REQUEST_TIMEOUT ||\n code === HTTP_STATUS.BAD_GATEWAY ||\n code === HTTP_STATUS.SERVICE_UNAVAILABLE ||\n code === HTTP_STATUS.GATEWAY_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 debug('looking for %o', proxy_key);\n\n // get http_proxy and no_proxy configs\n if (proxy_key in config) {\n this.proxy = config[proxy_key];\n debug('found %o in uplink config', this.proxy);\n } else if (proxy_key in mainconfig) {\n this.proxy = mainconfig[proxy_key];\n debug('found %o in main config', this.proxy);\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 (typeof noProxyList === 'string' && noProxyList.length) {\n noProxyList = noProxyList.split(',');\n }\n\n if (Array.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 debug('not using proxy, excluded by @{rule}', noProxyItem);\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 debug('using proxy @{proxy} for @{url}', this.proxy, this.url.href);\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/build/proxy.mjs CHANGED
@@ -223,13 +223,7 @@ var ProxyStorage = class {
223
223
  }).on("request", () => {
224
224
  this.last_request_time = Date.now();
225
225
  }).on("response", (eventResponse) => {
226
- this.logger.http({
227
- request: {
228
- method,
229
- url: uri
230
- },
231
- status: eventResponse !== null ? eventResponse.statusCode : "ERR"
232
- }, "@{!status}, req: '@{request.method} @{request.url}' (streaming)");
226
+ this.logUplinkResponse(method, uri, eventResponse);
233
227
  }).on("downloadProgress", (progress) => {
234
228
  if (progress.total) {
235
229
  debug("responseLength %s", progress.total);
@@ -261,6 +255,7 @@ var ProxyStorage = class {
261
255
  if (err.code === "ERR_NON_2XX_3XX_RESPONSE") {
262
256
  const code = err.response.statusCode;
263
257
  debug("error code %s", code);
258
+ this.logUplinkResponse(method, uri, err.response);
264
259
  if (code === HTTP_STATUS.NOT_FOUND) throw errorUtils.getNotFound(API_ERROR.NOT_PACKAGE_UPLINK);
265
260
  if (!(code >= HTTP_STATUS.OK && code < HTTP_STATUS.MULTIPLE_CHOICES)) {
266
261
  const error = errorUtils.getInternalError(`${API_ERROR.BAD_STATUS_CODE}: ${code}`);
@@ -274,6 +269,15 @@ var ProxyStorage = class {
274
269
  throw err;
275
270
  }
276
271
  }
272
+ logUplinkResponse(method, uri, response) {
273
+ this.logger.http({
274
+ request: {
275
+ method,
276
+ url: uri
277
+ },
278
+ status: response !== null ? response.statusCode : "ERR"
279
+ }, "@{!status}, req: '@{request.method} @{request.url}' (streaming)");
280
+ }
277
281
  fetchTarball(url, overrideOptions) {
278
282
  debug("fetching url for %s", url);
279
283
  const options = {
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.mjs","names":[],"sources":["../src/proxy.ts"],"sourcesContent":["import JSONStream from 'JSONStream';\nimport buildDebug from 'debug';\nimport type { Agents, Delays, RequestError, RetryOptions, Headers as gotHeaders } from 'got';\nimport got, { Options } from 'got';\nimport { isNil, isObject } from 'lodash-es';\nimport type Stream from 'node:stream';\nimport { PassThrough, Readable } from 'node:stream';\nimport { URL } from 'node:url';\n\nimport type { searchUtils } from '@verdaccio/core';\nimport {\n API_ERROR,\n HEADERS,\n HTTP_STATUS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n authUtils,\n constants,\n errorUtils,\n} from '@verdaccio/core';\nimport type { AgentOptionsConf, Config, Logger, Manifest, UpLinkConf } from '@verdaccio/types';\n\nimport CustomAgents from './agent';\nimport { parseInterval } from './proxy-utils';\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 url: string;\n abort: AbortController;\n query?: searchUtils.SearchQuery;\n headers?: Headers;\n retry?: Partial<RetryOptions>;\n onSearchPage?: (total: number | undefined) => void;\n};\nexport interface IProxy {\n uplinkName: string;\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: Delays;\n max_fails: number;\n fail_timeout: number;\n search(options: ProxySearchParams): Promise<Stream.Readable>;\n getRemoteMetadata(\n name: string,\n options: Partial<ISyncUplinksOptions>\n ): Promise<[Manifest, string]>;\n fetchTarball(\n url: string,\n options: Partial<Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'>> & {\n throwHttpErrors?: boolean;\n }\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 uplinkName: string;\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: Delays;\n public max_fails: number;\n public fail_timeout: number;\n public agent_options: AgentOptionsConf;\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<RetryOptions>;\n\n public constructor(\n uplinkName: string,\n config: UpLinkConfLocal,\n mainConfig: Config,\n logger: Logger,\n agent?: Agents\n ) {\n this.uplinkName = uplinkName;\n this.config = config;\n this.failed_requests = 0;\n this.userAgent = mainConfig.user_agent ?? 'hidden';\n this.ca = config.ca;\n this.logger = logger;\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 = {\n request: parseInterval(setConfig(this.config, 'timeout', '30s')),\n };\n debug('set timeout %s', this.timeout);\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 // `max_fails` is the circuit-breaker threshold (failed requests before the\n // uplink is considered offline) and must not drive the per-request retry\n // count — otherwise a high max_fails multiplies every uplink timeout by\n // that value. Retries have their own `retry` setting (default matches got).\n const retryConfig = setConfig(this.config, 'retry', 2);\n this.retry =\n typeof retryConfig === 'object' && retryConfig !== null\n ? (retryConfig as Partial<RetryOptions>)\n : { limit: Number(retryConfig) };\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 getHeaders(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 as any).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 && typeof tokenConf.token === 'string') {\n debug('use token from config');\n token = tokenConf.token;\n } else if (isNil(tokenConf.token_env) === false) {\n if (typeof tokenConf.token_env === 'string') {\n debug('use token from env %o', tokenConf.token_env);\n token = process.env[tokenConf.token_env];\n } else if (typeof tokenConf.token_env === 'boolean' && tokenConf.token_env) {\n debug('use token from env NPM_TOKEN');\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 debug('use token from env NPM_TOKEN');\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 debug('token type %o', type);\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 headers[HEADERS.AUTHORIZATION] = authUtils.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 */\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 getRemoteMetadata(\n name: string,\n options: Partial<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('getting metadata for package %s', name);\n let headers = this.getHeaders(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('set retry limit is %s', this.retry.limit);\n let response;\n let responseLength = 0;\n try {\n const retry = options?.retry ?? this.retry;\n debug('retry initial count %s', retry);\n response = await got(uri, {\n headers,\n responseType: 'json',\n method,\n agent: this.agent,\n retry,\n timeout: this.timeout,\n hooks: {\n afterResponse: [\n (afterResponse) => {\n const code = afterResponse.statusCode;\n debug('after response code is %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 (error: RequestError, count: number) => {\n debug('retry %s count: %s', uri, 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<any>('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: eventResponse !== null ? 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 with the original 304 status preserved\n if (response?.statusCode === HTTP_STATUS.NOT_MODIFIED) {\n const err = errorUtils.getNotFound(API_ERROR.NOT_MODIFIED_NO_DATA);\n err.code = HTTP_STATUS.NOT_MODIFIED;\n throw err;\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('error %s on uri %s', err.code, uri);\n if (err.code === 'ERR_NON_2XX_3XX_RESPONSE') {\n const code = err.response.statusCode;\n debug('error code %s', code);\n if (code === HTTP_STATUS.NOT_FOUND) {\n throw errorUtils.getNotFound(API_ERROR.NOT_PACKAGE_UPLINK);\n }\n\n if (!(code >= HTTP_STATUS.OK && code < HTTP_STATUS.MULTIPLE_CHOICES)) {\n const error = errorUtils.getInternalError(`${API_ERROR.BAD_STATUS_CODE}: ${code}`);\n // we need this code to identify outside which status code triggered the error\n error.remoteStatus = code;\n throw error;\n }\n } else if (this._isRequestTimeout(err)) {\n debug('error code timeout');\n throw errorUtils.getServiceUnavailable(API_ERROR.SERVER_TIME_OUT);\n }\n throw err;\n }\n }\n\n // FIXME: handle stream and retry\n public fetchTarball(\n url: string,\n overrideOptions: Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'> & {\n throwHttpErrors?: boolean;\n }\n ): any {\n debug('fetching url for %s', url);\n const options = { ...this.config, ...overrideOptions };\n let headers = this.getHeaders(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 // surface the outgoing tarball request so devops can observe which host a\n // tarball is fetched from (an autogenerated proxy shows as verdaccio-<pkg>)\n this.logger.http({ url, uplink: this.uplinkName }, 'fetching tarball from @{uplink} - @{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 ...(typeof overrideOptions.throwHttpErrors === 'boolean'\n ? { throwHttpErrors: overrideOptions.throwHttpErrors }\n : {}),\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({\n url,\n abort,\n retry,\n onSearchPage,\n }: ProxySearchParams): Promise<Stream.Readable> {\n try {\n const uri = this.buildUri(url);\n const headers = this.applyUplinkHeaders(this.getHeaders());\n this.logger.http(\n { uri, uplink: this.uplinkName },\n 'search request to uplink @{uplink} - @{uri}'\n );\n debug('searching on %o', uri);\n const response = got(uri, {\n headers,\n signal: abort ? abort.signal : undefined,\n agent: this.agent,\n timeout: this.timeout,\n retry: retry ?? this.retry,\n });\n\n const res = await (response.text() as unknown as Promise<string>);\n const total = JSON.parse(res).total;\n onSearchPage?.(Number.isSafeInteger(total) && total >= 0 ? total : undefined);\n debug('number of packages found: %o', total);\n const streamSearch = new PassThrough({ objectMode: true });\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 if (onSearchPage) {\n if (!abort?.signal.aborted) {\n this.logger.error(\n { errorMessage: err?.message, name: this.uplinkName },\n 'proxy uplink @{name} search error: @{errorMessage}'\n );\n }\n throw abort?.signal.aborted\n ? abort.signal.reason\n : errorUtils.getServiceUnavailable('uplink search failed');\n }\n debug('search error %s', err);\n if (err?.response?.statusCode === HTTP_STATUS.CONFLICT) {\n throw errorUtils.getInternalError(`bad status code ${err.response.statusCode} from uplink`);\n }\n if (!abort?.signal.aborted) {\n this.logger.error(\n { errorMessage: err?.message, name: this.uplinkName },\n 'proxy uplink @{name} search error: @{errorMessage}'\n );\n }\n throw err;\n }\n }\n\n private buildUri(path: string): string {\n const base = new URL(this.url);\n base.pathname = `${base.pathname.replace(/\\/+$/, '')}/`;\n return new URL(path.replace(/^\\/+/, ''), base).href;\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 * Check if the request timed out (network or http errors).\n * @param {RequestError} err\n * @return {boolean}\n */\n private _isRequestTimeout(err: RequestError): boolean {\n const code = err?.response?.statusCode;\n return (\n err.code === 'ETIMEDOUT' ||\n err.code === 'ESOCKETTIMEDOUT' ||\n err.code === 'ECONNRESET' ||\n code === HTTP_STATUS.REQUEST_TIMEOUT ||\n code === HTTP_STATUS.BAD_GATEWAY ||\n code === HTTP_STATUS.SERVICE_UNAVAILABLE ||\n code === HTTP_STATUS.GATEWAY_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 debug('looking for %o', proxy_key);\n\n // get http_proxy and no_proxy configs\n if (proxy_key in config) {\n this.proxy = config[proxy_key];\n debug('found %o in uplink config', this.proxy);\n } else if (proxy_key in mainconfig) {\n this.proxy = mainconfig[proxy_key];\n debug('found %o in main config', this.proxy);\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 (typeof noProxyList === 'string' && noProxyList.length) {\n noProxyList = noProxyList.split(',');\n }\n\n if (Array.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 debug('not using proxy, excluded by @{rule}', noProxyItem);\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 debug('using proxy @{proxy} for @{url}', this.proxy, this.url.href);\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":";;;;;;;;;;AAyBA,IAAM,QAAQ,WAAW,iBAAiB;AAE1C,IAAM,SAAS,SAAU,OAAe;CACtC,OAAO,mBAAmB,KAAK,CAAC,CAAC,QAAQ,QAAQ,GAAG;AACtD;AAGA,IAAM,oBAAoB,GADF,QAAQ,KACa;;;;AAK7C,IAAM,aAAa,QAAyB,KAAa,QAAgB;CACvE,OAAO,MAAM,OAAO,IAAI,MAAM,QAAQ,OAAO,OAAO;AACtD;;;;;AAyDA,IAAM,eAAN,MAAqC;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CAEA,YACE,YACA,QACA,YACA,QACA,OACA;EACA,KAAK,aAAa;EAClB,KAAK,SAAS;EACd,KAAK,kBAAkB;EACvB,KAAK,YAAY,WAAW,cAAc;EAC1C,KAAK,KAAK,OAAO;EACjB,KAAK,SAAS;EACd,KAAK,YAAY,WAAW;EAC5B,KAAK,gBAAgB,UAAU,KAAK,QAAQ,iBAAiB;GAC3D,WAAW;GACX,YAAY;GACZ,gBAAgB;EAClB,CAAC;EACD,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO,GAAG;EAClC,MAAM,UAAU,KAAK,IAAI,aAAa;EACtC,KAAK,YAAY,KAAK,IAAI,UAAU,QAAQ,YAAY,OAAO;EAC/D,KAAK,QAAQ,SAAS,KAAK,SAAS;EACpC,KAAK,OAAO,MAAM,KAAK,OAAO,IAAI,QAAQ,OAAO,EAAE;EAEnD,IAAI,KAAK,OAAO,WAAW,OAAO,KAAK,OAAO,OAAO,KAAK,KACxD,KAAK,OAAO,KACV;GACE,4BAA4B,KAAK,OAAO;GACxC;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI,CACb;EAIF,KAAK,SAAS,cAAc,UAAU,KAAK,QAAQ,UAAU,IAAI,CAAC;EAElE,KAAK,UAAU,EACb,SAAS,cAAc,UAAU,KAAK,QAAQ,WAAW,KAAK,CAAC,EACjE;EACA,MAAM,kBAAkB,KAAK,OAAO;EACpC,KAAK,YAAY,OAAO,UAAU,KAAK,QAAQ,aAAa,KAAK,OAAO,aAAa,CAAC,CAAC;EACvF,KAAK,eAAe,cAAc,UAAU,KAAK,QAAQ,gBAAgB,IAAI,CAAC;EAC9E,KAAK,aAAa,QAAQ,UAAU,KAAK,QAAQ,cAAc,IAAI,CAAC;EAKpE,MAAM,cAAc,UAAU,KAAK,QAAQ,SAAS,CAAC;EACrD,KAAK,QACH,OAAO,gBAAgB,YAAY,gBAAgB,OAC9C,cACD,EAAE,OAAO,OAAO,WAAW,EAAE;CACrC;CAEA,WAAmB;EACjB,IAAI,CAAC,KAAK,OAGR,OAAO,IADmB,aAAa,KAAK,OAAO,KAAK,KAAK,OAAO,KAAK,aAClE,CAAA,CAAc,IAAI;OAEzB,OAAO,KAAK;CAEhB;CAEA,WAAkB,UAAU,CAAC,GAAe;EAC1C,MAAM,SAAS,QAAQ;EACvB,MAAM,iBAAiB,QAAQ;EAC/B,MAAM,YAAY,QAAQ;EAE1B,QAAQ,UAAU,QAAQ,WAAW;EACrC,QAAQ,kBAAkB,QAAQ,mBAAmB;EAErD,QAAQ,aAAa,QAAQ,cAAc,QAAQ,KAAK,UAAU;EAClE,OAAO,KAAK,YAAY,OAAO;CACjC;;;;;;;CAQA,YAAoB,SAAiC;EACnD,MAAM,EAAE,SAAS,KAAK;EACtB,IAAI,OAAO,SAAS,eAAe,OAAO,QAAQ,QAAQ,mBAAmB,UAC3E,OAAO;EAGT,IAAI,SAAS,IAAI,MAAM,SAAS,SAAU,KAAa,KAAK,MAAM,OAChE,KAAK,gBAAgB,cAAc;EAMrC,IAAI;EACJ,MAAM,YAAiB;EACvB,IAAI,MAAM,UAAU,KAAK,MAAM,SAAS,OAAO,UAAU,UAAU,UAAU;GAC3E,MAAM,uBAAuB;GAC7B,QAAQ,UAAU;EACpB,OAAO,IAAI,MAAM,UAAU,SAAS,MAAM,OAAO;GAC/C,IAAI,OAAO,UAAU,cAAc,UAAU;IAC3C,MAAM,yBAAyB,UAAU,SAAS;IAClD,QAAQ,QAAQ,IAAI,UAAU;GAChC,OAAO,IAAI,OAAO,UAAU,cAAc,aAAa,UAAU,WAAW;IAC1E,MAAM,8BAA8B;IACpC,QAAQ,QAAQ,IAAI;GACtB,OAAO;IACL,KAAK,OAAO,MAAM,UAAU,WAAW,cAAc;IACrD,KAAK,gBAAgB,UAAU,WAAW,cAAc;GAC1D;EACF,OAAO;GACL,MAAM,8BAA8B;GACpC,QAAQ,QAAQ,IAAI;EACtB;EAEA,IAAI,OAAO,UAAU,aACnB,KAAK,gBAAgB,UAAU,WAAW,cAAc;EAI1D,MAAM,OAAO,UAAU,QAAQ;EAC/B,MAAM,iBAAiB,IAAI;EAC3B,KAAK,wBAAwB,SAAS,MAAM,KAAK;EAEjD,OAAO;CACT;;;;;;CAOA,gBAAwB,SAAwB;EAC9C,KAAK,OAAO,MAAM,OAAO;EACzB,MAAM,IAAI,MAAM,OAAO;CACzB;;;;;;;;CASA,wBAAgC,SAAc,MAAc,OAAkB;EAC5E,MAAM,QAAgB,KAAK,YAAY;EAEvC,IAAI,UAAU,aAAa,YAAY,KAAK,UAAU,YAAY,YAAY,GAC5E,KAAK,gBAAgB,cAAc,MAAM,cAAc;EAGzD,QAAQ,QAAQ,iBAAiB,UAAU,WAAW,MAAM,KAAK;CACnE;;;;;;;;;;;;;;;;;;;;CAqBA,mBAA2B,SAAiC;EAC1D,IAAI,CAAC,KAAK,OAAO,SACf,OAAO;EAKT,KAAK,MAAM,OAAO,KAAK,OAAO,SAC5B,QAAQ,OAAO,KAAK,OAAO,QAAQ;EAErC,OAAO;CACT;CAEA,MAAa,kBACX,MACA,SAC6B;EAC7B,IAAI,KAAK,kBAAkB,GACzB,MAAM,WAAW,iBAAiB,UAAU,cAAc;EAI5D,MAAM,mCAAmC,IAAI;EAC7C,IAAI,UAAU,KAAK,WAAW,SAAS,OAAO;EAC9C,UAAU,KAAK,gBAAgB,SAAS,QAAQ,aAAa;EAC7D,UAAU,KAAK,mBAAmB,OAAO;EAEzC,IAAI,MAAM,QAAQ,IAAI,MAAM,OAAO;GACjC,QAAQ,QAAQ,cAAc,QAAQ;GACtC,QAAQ,QAAQ,UAAU;EAC5B;EACA,MAAM,SAAS,QAAQ,UAAU;EACjC,MAAM,MAAM,KAAK,OAAO,MAAM,IAAI,OAAO,IAAI;EAC7C,MAAM,yBAAyB,KAAK,MAAM,KAAK;EAC/C,IAAI;EACJ,IAAI,iBAAiB;EACrB,IAAI;GACF,MAAM,QAAQ,SAAS,SAAS,KAAK;GACrC,MAAM,0BAA0B,KAAK;GACrC,WAAW,MAAM,IAAI,KAAK;IACxB;IACA,cAAc;IACd;IACA,OAAO,KAAK;IACZ;IACA,SAAS,KAAK;IACd,OAAO;KACL,eAAe,EACZ,kBAAkB;MACjB,MAAM,OAAO,cAAc;MAC3B,MAAM,6BAA6B,IAAI;MACvC,IAAI,QAAQ,YAAY,MAAM,OAAO,YAAY,kBAC3C;WAAA,KAAK,mBAAmB,KAAK,WAAW;QAC1C,KAAK,kBAAkB;QACvB,KAAK,OAAO,KACV,EACE,MAAM,KAAK,IAAI,KACjB,GACA,4BACF;OACF;;MAGF,OAAO;KACT,CACF;KACA,aAAa,EACV,OAAqB,UAAkB;MACtC,MAAM,sBAAsB,KAAK,KAAK;MACtC,KAAK,kBAAkB,SAAS;MAChC,KAAK,OAAO,KACV;OACE,SAAS;QACC;QACR,KAAK;OACP;OACA,OAAO,MAAM;OACb,YAAY,KAAK;MACnB,GACA,6DACF;MACA,IAAI,KAAK,mBAAmB,KAAK,WAC/B,KAAK,OAAO,KACV,EACE,MAAM,KAAK,IAAI,KACjB,GACA,6BACF;KAEJ,CACF;IACF;GACF,CAAC,CAAC,CACC,GAAG,iBAAiB;IACnB,KAAK,oBAAoB,KAAK,IAAI;GACpC,CAAC,CAAC,CACD,GAAQ,aAAa,kBAAkB;IAEtC,KAAK,OAAO,KACV;KACE,SAAS;MACC;MACR,KAAK;KACP;KACA,QAAQ,kBAAkB,OAAO,cAAc,aAAa;IAC9D,GACA,iEACF;GACF,CAAC,CAAC,CACD,GAAG,qBAAqB,aAAa;IACpC,IAAI,SAAS,OAAO;KAClB,MAAM,qBAAqB,SAAS,KAAK;KACzC,iBAAiB,SAAS;IAC5B;GACF,CAAC;GACH,MAAM,OAAO,SAAS,QAAQ;GAC9B,MAAM,OAAO,SAAS;GAItB,IAAI,UAAU,eAAe,YAAY,cAAc;IACrD,MAAM,MAAM,WAAW,YAAY,UAAU,oBAAoB;IACjE,IAAI,OAAO,YAAY;IACvB,MAAM;GACR;GAEA,MAAM,kBAAkB,GAAG;GAE3B,KAAK,OAAO,KACV;IAEE,SAAS;KAAU;KAAQ,KAAK;IAAI;IACpC,QAAQ,SAAS;IACjB,OAAO;KACL,IAAI,SAAS,OAAO,KAAK,UAAU,SAAS,IAAI,CAAC,CAAC,SAAS;KAC3D,KAAK,kBAAkB;IACzB;GACF,GACA,qDACF;GACA,OAAO,CAAC,MAAM,IAAI;EACpB,SAAS,KAAU;GACjB,MAAM,sBAAsB,IAAI,MAAM,GAAG;GACzC,IAAI,IAAI,SAAS,4BAA4B;IAC3C,MAAM,OAAO,IAAI,SAAS;IAC1B,MAAM,iBAAiB,IAAI;IAC3B,IAAI,SAAS,YAAY,WACvB,MAAM,WAAW,YAAY,UAAU,kBAAkB;IAG3D,IAAI,EAAE,QAAQ,YAAY,MAAM,OAAO,YAAY,mBAAmB;KACpE,MAAM,QAAQ,WAAW,iBAAiB,GAAG,UAAU,gBAAgB,IAAI,MAAM;KAEjF,MAAM,eAAe;KACrB,MAAM;IACR;GACF,OAAO,IAAI,KAAK,kBAAkB,GAAG,GAAG;IACtC,MAAM,oBAAoB;IAC1B,MAAM,WAAW,sBAAsB,UAAU,eAAe;GAClE;GACA,MAAM;EACR;CACF;CAGA,aACE,KACA,iBAGK;EACL,MAAM,uBAAuB,GAAG;EAChC,MAAM,UAAU;GAAE,GAAG,KAAK;GAAQ,GAAG;EAAgB;EACrD,IAAI,UAAU,KAAK,WAAW,SAAS,OAAO;EAC9C,UAAU,KAAK,gBAAgB,SAAS,QAAQ,aAAa;EAC7D,UAAU,KAAK,mBAAmB,OAAO;EAEzC,IAAI,MAAM,QAAQ,IAAI,MAAM,OAAO;GACjC,QAAQ,QAAQ,cAAc,QAAQ;GACtC,QAAQ,QAAQ,UAAU;EAC5B;EACA,MAAM,SAAS;EAEf,MAAM,sBAAsB,GAAG;EAG/B,KAAK,OAAO,KAAK;GAAE;GAAK,QAAQ,KAAK;EAAW,GAAG,0CAA0C;EAkB7F,OAhBmB,IAChB,OAAO,KAAK;GACX;GACA;GACA,OAAO,KAAK;GAEZ,OAAO,KAAK,SAAS,SAAS;GAC9B,SAAS,KAAK;GACd,GAAI,OAAO,gBAAgB,oBAAoB,YAC3C,EAAE,iBAAiB,gBAAgB,gBAAgB,IACnD,CAAC;EACP,CAAC,CAAC,CACD,GAAG,iBAAiB;GACnB,KAAK,oBAAoB,KAAK,IAAI;EACpC,CAEK;CACT;;;;;;CAOA,MAAa,OAAO,EAClB,KACA,OACA,OACA,gBAC8C;EAC9C,IAAI;GACF,MAAM,MAAM,KAAK,SAAS,GAAG;GAC7B,MAAM,UAAU,KAAK,mBAAmB,KAAK,WAAW,CAAC;GACzD,KAAK,OAAO,KACV;IAAE;IAAK,QAAQ,KAAK;GAAW,GAC/B,6CACF;GACA,MAAM,mBAAmB,GAAG;GAS5B,MAAM,MAAM,MARK,IAAI,KAAK;IACxB;IACA,QAAQ,QAAQ,MAAM,SAAS,KAAA;IAC/B,OAAO,KAAK;IACZ,SAAS,KAAK;IACd,OAAO,SAAS,KAAK;GACvB,CAEmB,CAAA,CAAS,KAAK;GACjC,MAAM,QAAQ,KAAK,MAAM,GAAG,CAAC,CAAC;GAC9B,eAAe,OAAO,cAAc,KAAK,KAAK,SAAS,IAAI,QAAQ,KAAA,CAAS;GAC5E,MAAM,gCAAgC,KAAK;GAC3C,MAAM,eAAe,IAAI,YAAY,EAAE,YAAY,KAAK,CAAC;GAGzD,SAFgC,KAAK,GAErC,CAAA,CAAe,KAAK,WAAW,MAAM,SAAS,CAAC,CAAC,CAAC,KAAK,cAAc,EAAE,KAAK,KAAK,CAAC;GACjF,OAAO;EACT,SAAS,KAAU;GACjB,IAAI,cAAc;IAChB,IAAI,CAAC,OAAO,OAAO,SACjB,KAAK,OAAO,MACV;KAAE,cAAc,KAAK;KAAS,MAAM,KAAK;IAAW,GACpD,oDACF;IAEF,MAAM,OAAO,OAAO,UAChB,MAAM,OAAO,SACb,WAAW,sBAAsB,sBAAsB;GAC7D;GACA,MAAM,mBAAmB,GAAG;GAC5B,IAAI,KAAK,UAAU,eAAe,YAAY,UAC5C,MAAM,WAAW,iBAAiB,mBAAmB,IAAI,SAAS,WAAW,aAAa;GAE5F,IAAI,CAAC,OAAO,OAAO,SACjB,KAAK,OAAO,MACV;IAAE,cAAc,KAAK;IAAS,MAAM,KAAK;GAAW,GACpD,oDACF;GAEF,MAAM;EACR;CACF;CAEA,SAAiB,MAAsB;EACrC,MAAM,OAAO,IAAI,IAAI,KAAK,GAAG;EAC7B,KAAK,WAAW,GAAG,KAAK,SAAS,QAAQ,QAAQ,EAAE,EAAE;EACrD,OAAO,IAAI,IAAI,KAAK,QAAQ,QAAQ,EAAE,GAAG,IAAI,CAAC,CAAC;CACjD;CAEA,gBAAwB,SAAqB,eAAoC;EAK/E,IAAI,CAAC,KAAK,OACR,QAAQ,QAAQ,kBACb,QAAQ,qBAAqB,QAAQ,qBAAqB,OAAO,MAAM;EAI5E,QAAQ,SAAS,QAAQ,SAAS,QAAQ,SAAS,OAAO;EAC1D,QAAQ,UAAU,SAAS,KAAK,YAAY;EAE5C,OAAO;CACT;;;;;;CAOA,oBAAqC;EACnC,OACE,KAAK,mBAAmB,KAAK,aAC7B,KAAK,IAAI,KAAK,IAAI,IAAK,KAAK,iBAA4B,IAAI,KAAK;CAErE;;;;;;CAOA,kBAA0B,KAA4B;EACpD,MAAM,OAAO,KAAK,UAAU;EAC5B,OACE,IAAI,SAAS,eACb,IAAI,SAAS,qBACb,IAAI,SAAS,gBACb,SAAS,YAAY,mBACrB,SAAS,YAAY,eACrB,SAAS,YAAY,uBACrB,SAAS,YAAY;CAEzB;;;;;;;;CASA,YACE,UACA,QACA,YACA,SACM;EACN,IAAI;EACJ,MAAM,YAAoB,UAAU,gBAAgB;EACpD,MAAM,kBAAkB,SAAS;EAGjC,IAAI,aAAa,QAAQ;GACvB,KAAK,QAAQ,OAAO;GACpB,MAAM,6BAA6B,KAAK,KAAK;EAC/C,OAAO,IAAI,aAAa,YAAY;GAClC,KAAK,QAAQ,WAAW;GACxB,MAAM,2BAA2B,KAAK,KAAK;EAC7C;EACA,IAAI,cAAc,QAChB,cAAc,OAAO;OAChB,IAAI,cAAc,YACvB,cAAc,WAAW;EAI3B,IAAI,SAAS,OAAO,KAClB,WAAW,MAAM;EAGnB,IAAI,OAAO,gBAAgB,YAAY,YAAY,QACjD,cAAc,YAAY,MAAM,GAAG;EAGrC,IAAI,MAAM,QAAQ,WAAW,GAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;GAC3C,IAAI,cAAc,YAAY;GAC9B,IAAI,YAAY,OAAO,KACrB,cAAc,MAAM;GAEtB,IAAI,SAAS,SAAS,WAAW,GAAG;IAClC,IAAI,KAAK,OAAO;KACd,MAAM,wCAAwC,WAAW;KACzD,KAAK,OAAO,MACV;MAAE,KAAK,KAAK,IAAI;MAAM,MAAM;KAAY,GACxC,sDACF;KACA,KAAK,QAAQ,KAAA;IACf;IACA;GACF;EACF;EAGF,IAAI,OAAO,KAAK,UAAU,UAAU;GAClC,MAAM,mCAAmC,KAAK,OAAO,KAAK,IAAI,IAAI;GAClE,KAAK,OAAO,MACV;IAAE,KAAK,KAAK,IAAI;IAAM,OAAO,KAAK;GAAM,GACxC,iCACF;EACF;CACF;AACF"}
1
+ {"version":3,"file":"proxy.mjs","names":[],"sources":["../src/proxy.ts"],"sourcesContent":["import JSONStream from 'JSONStream';\nimport buildDebug from 'debug';\nimport type { Agents, Delays, RequestError, RetryOptions, Headers as gotHeaders } from 'got';\nimport got, { Options } from 'got';\nimport { isNil, isObject } from 'lodash-es';\nimport type Stream from 'node:stream';\nimport { PassThrough, Readable } from 'node:stream';\nimport { URL } from 'node:url';\n\nimport type { searchUtils } from '@verdaccio/core';\nimport {\n API_ERROR,\n HEADERS,\n HTTP_STATUS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n authUtils,\n constants,\n errorUtils,\n} from '@verdaccio/core';\nimport type { AgentOptionsConf, Config, Logger, Manifest, UpLinkConf } from '@verdaccio/types';\n\nimport CustomAgents from './agent';\nimport { parseInterval } from './proxy-utils';\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 url: string;\n abort: AbortController;\n query?: searchUtils.SearchQuery;\n headers?: Headers;\n retry?: Partial<RetryOptions>;\n onSearchPage?: (total: number | undefined) => void;\n};\nexport interface IProxy {\n uplinkName: string;\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: Delays;\n max_fails: number;\n fail_timeout: number;\n search(options: ProxySearchParams): Promise<Stream.Readable>;\n getRemoteMetadata(\n name: string,\n options: Partial<ISyncUplinksOptions>\n ): Promise<[Manifest, string]>;\n fetchTarball(\n url: string,\n options: Partial<Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'>> & {\n throwHttpErrors?: boolean;\n }\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 uplinkName: string;\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: Delays;\n public max_fails: number;\n public fail_timeout: number;\n public agent_options: AgentOptionsConf;\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<RetryOptions>;\n\n public constructor(\n uplinkName: string,\n config: UpLinkConfLocal,\n mainConfig: Config,\n logger: Logger,\n agent?: Agents\n ) {\n this.uplinkName = uplinkName;\n this.config = config;\n this.failed_requests = 0;\n this.userAgent = mainConfig.user_agent ?? 'hidden';\n this.ca = config.ca;\n this.logger = logger;\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 = {\n request: parseInterval(setConfig(this.config, 'timeout', '30s')),\n };\n debug('set timeout %s', this.timeout);\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 // `max_fails` is the circuit-breaker threshold (failed requests before the\n // uplink is considered offline) and must not drive the per-request retry\n // count — otherwise a high max_fails multiplies every uplink timeout by\n // that value. Retries have their own `retry` setting (default matches got).\n const retryConfig = setConfig(this.config, 'retry', 2);\n this.retry =\n typeof retryConfig === 'object' && retryConfig !== null\n ? (retryConfig as Partial<RetryOptions>)\n : { limit: Number(retryConfig) };\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 getHeaders(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 as any).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 && typeof tokenConf.token === 'string') {\n debug('use token from config');\n token = tokenConf.token;\n } else if (isNil(tokenConf.token_env) === false) {\n if (typeof tokenConf.token_env === 'string') {\n debug('use token from env %o', tokenConf.token_env);\n token = process.env[tokenConf.token_env];\n } else if (typeof tokenConf.token_env === 'boolean' && tokenConf.token_env) {\n debug('use token from env NPM_TOKEN');\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 debug('use token from env NPM_TOKEN');\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 debug('token type %o', type);\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 headers[HEADERS.AUTHORIZATION] = authUtils.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 */\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 getRemoteMetadata(\n name: string,\n options: Partial<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('getting metadata for package %s', name);\n let headers = this.getHeaders(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('set retry limit is %s', this.retry.limit);\n let response;\n let responseLength = 0;\n try {\n const retry = options?.retry ?? this.retry;\n debug('retry initial count %s', retry);\n response = await got(uri, {\n headers,\n responseType: 'json',\n method,\n agent: this.agent,\n retry,\n timeout: this.timeout,\n hooks: {\n afterResponse: [\n (afterResponse) => {\n const code = afterResponse.statusCode;\n debug('after response code is %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 (error: RequestError, count: number) => {\n debug('retry %s count: %s', uri, 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<any>('response', (eventResponse) => {\n this.logUplinkResponse(method, uri, eventResponse);\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 with the original 304 status preserved\n if (response?.statusCode === HTTP_STATUS.NOT_MODIFIED) {\n const err = errorUtils.getNotFound(API_ERROR.NOT_MODIFIED_NO_DATA);\n err.code = HTTP_STATUS.NOT_MODIFIED;\n throw err;\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('error %s on uri %s', err.code, uri);\n if (err.code === 'ERR_NON_2XX_3XX_RESPONSE') {\n const code = err.response.statusCode;\n debug('error code %s', code);\n // got only emits `response` for the response the promise resolves with\n this.logUplinkResponse(method, uri, err.response);\n if (code === HTTP_STATUS.NOT_FOUND) {\n throw errorUtils.getNotFound(API_ERROR.NOT_PACKAGE_UPLINK);\n }\n\n if (!(code >= HTTP_STATUS.OK && code < HTTP_STATUS.MULTIPLE_CHOICES)) {\n const error = errorUtils.getInternalError(`${API_ERROR.BAD_STATUS_CODE}: ${code}`);\n // we need this code to identify outside which status code triggered the error\n error.remoteStatus = code;\n throw error;\n }\n } else if (this._isRequestTimeout(err)) {\n debug('error code timeout');\n throw errorUtils.getServiceUnavailable(API_ERROR.SERVER_TIME_OUT);\n }\n throw err;\n }\n }\n\n private logUplinkResponse(method: string, uri: string, response: { statusCode: number } | null) {\n this.logger.http(\n {\n request: { method, url: uri },\n status: response !== null ? response.statusCode : 'ERR',\n },\n \"@{!status}, req: '@{request.method} @{request.url}' (streaming)\"\n );\n }\n\n // FIXME: handle stream and retry\n public fetchTarball(\n url: string,\n overrideOptions: Pick<ISyncUplinksOptions, 'remoteAddress' | 'etag' | 'retry'> & {\n throwHttpErrors?: boolean;\n }\n ): any {\n debug('fetching url for %s', url);\n const options = { ...this.config, ...overrideOptions };\n let headers = this.getHeaders(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 // surface the outgoing tarball request so devops can observe which host a\n // tarball is fetched from (an autogenerated proxy shows as verdaccio-<pkg>)\n this.logger.http({ url, uplink: this.uplinkName }, 'fetching tarball from @{uplink} - @{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 ...(typeof overrideOptions.throwHttpErrors === 'boolean'\n ? { throwHttpErrors: overrideOptions.throwHttpErrors }\n : {}),\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({\n url,\n abort,\n retry,\n onSearchPage,\n }: ProxySearchParams): Promise<Stream.Readable> {\n try {\n const uri = this.buildUri(url);\n const headers = this.applyUplinkHeaders(this.getHeaders());\n this.logger.http(\n { uri, uplink: this.uplinkName },\n 'search request to uplink @{uplink} - @{uri}'\n );\n debug('searching on %o', uri);\n const response = got(uri, {\n headers,\n signal: abort ? abort.signal : undefined,\n agent: this.agent,\n timeout: this.timeout,\n retry: retry ?? this.retry,\n });\n\n const res = await (response.text() as unknown as Promise<string>);\n const total = JSON.parse(res).total;\n onSearchPage?.(Number.isSafeInteger(total) && total >= 0 ? total : undefined);\n debug('number of packages found: %o', total);\n const streamSearch = new PassThrough({ objectMode: true });\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 if (onSearchPage) {\n if (!abort?.signal.aborted) {\n this.logger.error(\n { errorMessage: err?.message, name: this.uplinkName },\n 'proxy uplink @{name} search error: @{errorMessage}'\n );\n }\n throw abort?.signal.aborted\n ? abort.signal.reason\n : errorUtils.getServiceUnavailable('uplink search failed');\n }\n debug('search error %s', err);\n if (err?.response?.statusCode === HTTP_STATUS.CONFLICT) {\n throw errorUtils.getInternalError(`bad status code ${err.response.statusCode} from uplink`);\n }\n if (!abort?.signal.aborted) {\n this.logger.error(\n { errorMessage: err?.message, name: this.uplinkName },\n 'proxy uplink @{name} search error: @{errorMessage}'\n );\n }\n throw err;\n }\n }\n\n private buildUri(path: string): string {\n const base = new URL(this.url);\n base.pathname = `${base.pathname.replace(/\\/+$/, '')}/`;\n return new URL(path.replace(/^\\/+/, ''), base).href;\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 * Check if the request timed out (network or http errors).\n * @param {RequestError} err\n * @return {boolean}\n */\n private _isRequestTimeout(err: RequestError): boolean {\n const code = err?.response?.statusCode;\n return (\n err.code === 'ETIMEDOUT' ||\n err.code === 'ESOCKETTIMEDOUT' ||\n err.code === 'ECONNRESET' ||\n code === HTTP_STATUS.REQUEST_TIMEOUT ||\n code === HTTP_STATUS.BAD_GATEWAY ||\n code === HTTP_STATUS.SERVICE_UNAVAILABLE ||\n code === HTTP_STATUS.GATEWAY_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 debug('looking for %o', proxy_key);\n\n // get http_proxy and no_proxy configs\n if (proxy_key in config) {\n this.proxy = config[proxy_key];\n debug('found %o in uplink config', this.proxy);\n } else if (proxy_key in mainconfig) {\n this.proxy = mainconfig[proxy_key];\n debug('found %o in main config', this.proxy);\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 (typeof noProxyList === 'string' && noProxyList.length) {\n noProxyList = noProxyList.split(',');\n }\n\n if (Array.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 debug('not using proxy, excluded by @{rule}', noProxyItem);\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 debug('using proxy @{proxy} for @{url}', this.proxy, this.url.href);\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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"uplink-util.js","names":[],"sources":["../src/uplink-util.ts"],"sourcesContent":["import type { Config, Logger, Manifest } from '@verdaccio/types';\n\nimport type { IProxy } from './index';\nimport { ProxyStorage } from './index';\n\nexport interface ProxyInstanceList {\n [key: string]: IProxy;\n}\n\n/**\n * Set up uplinks for each proxy configuration.\n */\nexport function setupUpLinks(config: Config, logger: Logger): ProxyInstanceList {\n const uplinks: ProxyInstanceList = {};\n\n for (const uplinkName of Object.keys(config.uplinks)) {\n // instance for each up-link definition\n const proxy: IProxy = new ProxyStorage(uplinkName, config.uplinks[uplinkName], config, logger);\n uplinks[uplinkName] = proxy;\n }\n\n return uplinks;\n}\n\nexport function updateVersionsHiddenUpLinkNext(manifest: Manifest, upLink: IProxy): Manifest {\n const { versions } = manifest;\n const versionsList = Object.keys(versions);\n if (versionsList.length === 0) {\n return manifest;\n }\n\n for (const version of versionsList) {\n // holds a \"hidden\" value to be used by the package storage.\n versions[version][Symbol.for('__verdaccio_uplink')] = upLink.uplinkName;\n }\n\n return { ...manifest, versions };\n}\n"],"mappings":";;;;;;AAYA,SAAgB,aAAa,QAAgB,QAAmC;CAC9E,MAAM,UAA6B,CAAC;CAEpC,KAAK,MAAM,cAAc,OAAO,KAAK,OAAO,OAAO,GAGjD,QAAQ,cAAc,IADI,cAAA,aAAa,YAAY,OAAO,QAAQ,aAAa,QAAQ,MACjE;CAGxB,OAAO;AACT;AAEA,SAAgB,+BAA+B,UAAoB,QAA0B;CAC3F,MAAM,EAAE,aAAa;CACrB,MAAM,eAAe,OAAO,KAAK,QAAQ;CACzC,IAAI,aAAa,WAAW,GAC1B,OAAO;CAGT,KAAK,MAAM,WAAW,cAEpB,SAAS,QAAQ,CAAC,OAAO,IAAI,oBAAoB,KAAK,OAAO;CAG/D,OAAO;EAAE,GAAG;EAAU;CAAS;AACjC"}
1
+ {"version":3,"file":"uplink-util.js","names":["ProxyStorage"],"sources":["../src/uplink-util.ts"],"sourcesContent":["import type { Config, Logger, Manifest } from '@verdaccio/types';\n\nimport type { IProxy } from './index';\nimport { ProxyStorage } from './index';\n\nexport interface ProxyInstanceList {\n [key: string]: IProxy;\n}\n\n/**\n * Set up uplinks for each proxy configuration.\n */\nexport function setupUpLinks(config: Config, logger: Logger): ProxyInstanceList {\n const uplinks: ProxyInstanceList = {};\n\n for (const uplinkName of Object.keys(config.uplinks)) {\n // instance for each up-link definition\n const proxy: IProxy = new ProxyStorage(uplinkName, config.uplinks[uplinkName], config, logger);\n uplinks[uplinkName] = proxy;\n }\n\n return uplinks;\n}\n\nexport function updateVersionsHiddenUpLinkNext(manifest: Manifest, upLink: IProxy): Manifest {\n const { versions } = manifest;\n const versionsList = Object.keys(versions);\n if (versionsList.length === 0) {\n return manifest;\n }\n\n for (const version of versionsList) {\n // holds a \"hidden\" value to be used by the package storage.\n versions[version][Symbol.for('__verdaccio_uplink')] = upLink.uplinkName;\n }\n\n return { ...manifest, versions };\n}\n"],"mappings":";;;;;;AAYA,SAAgB,aAAa,QAAgB,QAAmC;CAC9E,MAAM,UAA6B,CAAC;CAEpC,KAAK,MAAM,cAAc,OAAO,KAAK,OAAO,OAAO,GAGjD,QAAQ,cAAc,IADIA,cAAAA,aAAa,YAAY,OAAO,QAAQ,aAAa,QAAQ,MACjE;CAGxB,OAAO;AACT;AAEA,SAAgB,+BAA+B,UAAoB,QAA0B;CAC3F,MAAM,EAAE,aAAa;CACrB,MAAM,eAAe,OAAO,KAAK,QAAQ;CACzC,IAAI,aAAa,WAAW,GAC1B,OAAO;CAGT,KAAK,MAAM,WAAW,cAEpB,SAAS,QAAQ,CAAC,OAAO,IAAI,oBAAoB,KAAK,OAAO;CAG/D,OAAO;EAAE,GAAG;EAAU;CAAS;AACjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdaccio/proxy",
3
- "version": "9.0.0-next-9.36",
3
+ "version": "9.0.0-next-9.37",
4
4
  "description": "Verdaccio Proxy Fetcher",
5
5
  "main": "./build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -33,23 +33,23 @@
33
33
  "node": ">=24"
34
34
  },
35
35
  "dependencies": {
36
- "@verdaccio/config": "9.0.0-next-9.36",
37
- "@verdaccio/core": "9.0.0-next-9.36",
36
+ "@verdaccio/config": "9.0.0-next-9.37",
37
+ "@verdaccio/core": "9.0.0-next-9.37",
38
38
  "JSONStream": "1.3.5",
39
39
  "debug": "4.4.3",
40
- "got": "15.1.0",
40
+ "got": "16.1.0",
41
41
  "hpagent": "1.2.0",
42
42
  "lodash-es": "4.18.1"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/lodash-es": "4.17.12",
46
- "@verdaccio/logger": "9.0.0-next-9.36",
46
+ "@verdaccio/logger": "9.0.0-next-9.37",
47
47
  "@verdaccio/types": "14.0.0-next-9.17",
48
48
  "get-stream": "9.0.1",
49
49
  "nock": "13.5.6",
50
50
  "rimraf": "6.1.3",
51
- "vite": "8.2.2",
52
- "vitest": "4.1.11"
51
+ "vite": "8.3.4",
52
+ "vitest": "5.0.5"
53
53
  },
54
54
  "funding": {
55
55
  "type": "opencollective",
@@ -71,7 +71,7 @@
71
71
  },
72
72
  "scripts": {
73
73
  "clean": "rimraf ./build",
74
- "test": "vitest run",
74
+ "test": "vitest run --fsModuleCachePath node_modules/.vitest-cache",
75
75
  "watch": "vite build --watch",
76
76
  "build": "vite build"
77
77
  }