-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Support VSO package manager registry #2507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| //registry.yarnpkg.com/:_authToken=abc123 | ||
| //registry.yarnpkg.com/:always-auth=true | ||
| @types:registry=https://registry.yarnpkg.com |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| //registry.yarnpkg.com/:_authToken=abc123 | ||
| //registry.yarnpkg.com/:always-auth=true | ||
| @types:registry=https://registry.yarnpkg.com/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,18 +2,25 @@ | |
|
|
||
| import url from 'url'; | ||
|
|
||
| const SUFFIX_VISUALSTUDIO = '.pkgs.visualstudio.com'; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I missed that detail earlier. |
||
|
|
||
| export default function isRequestToRegistry(requestUrl: string, registry: string): boolean { | ||
| const requestParsed = url.parse(requestUrl); | ||
| const registryParsed = url.parse(registry); | ||
| const requestHost = requestParsed.hostname || ''; | ||
| const registryHost = registryParsed.hostname || ''; | ||
| const requestPort = getPortOrDefaultPort(requestParsed.port, requestParsed.protocol); | ||
| const registryPort = getPortOrDefaultPort(registryParsed.port, registryParsed.protocol); | ||
| const requestPath = requestParsed.path || ''; | ||
| const registryPath = registryParsed.path || ''; | ||
|
|
||
| return (requestParsed.protocol === registryParsed.protocol) && | ||
| (requestParsed.hostname === registryParsed.hostname) && | ||
| (requestPort === registryPort) && | ||
| requestPath.startsWith(registryPath); | ||
| (requestHost === registryHost) && | ||
| (requestPort === registryPort) && ( | ||
| requestPath.startsWith(registryPath) || | ||
| // For pkgs.visualstudio.com, the package path does not prefix with the registry path | ||
| requestHost.endsWith(SUFFIX_VISUALSTUDIO) | ||
| ); | ||
| } | ||
|
|
||
| function getPortOrDefaultPort(port: ?string, protocol: ?string): ?string { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ import * as fs from '../util/fs.js'; | |
| import NpmResolver from '../resolvers/registries/npm-resolver.js'; | ||
| import envReplace from '../util/env-replace.js'; | ||
| import Registry from './base-registry.js'; | ||
| import {addSuffix, removePrefix} from '../util/misc'; | ||
| import {addSuffix} from '../util/misc'; | ||
| import isRequestToRegistry from './is-request-to-registry.js'; | ||
|
|
||
| const userHome = require('../util/user-home-dir').default; | ||
|
|
@@ -17,6 +17,8 @@ const url = require('url'); | |
| const ini = require('ini'); | ||
|
|
||
| const DEFAULT_REGISTRY = 'https://registry.npmjs.org/'; | ||
| const REGEX_REGISTRY_PREFIX = /^https?:/; | ||
| const REGEX_REGISTRY_SUFFIX = /registry\/?$/; | ||
|
|
||
| function getGlobalPrefix(): string { | ||
| if (process.env.PREFIX) { | ||
|
|
@@ -50,16 +52,14 @@ export default class NpmRegistry extends Registry { | |
| return name.replace('/', '%2f'); | ||
| } | ||
|
|
||
| request(pathname: string, opts?: RegistryRequestOptions = {}): Promise<*> { | ||
| const registry = addSuffix(this.getRegistry(pathname), '/'); | ||
| request(pathname: string, opts?: RegistryRequestOptions = {}, packageName: ?string): Promise<*> { | ||
| const registry = this.getRegistry(packageName || pathname); | ||
| const requestUrl = url.resolve(registry, pathname); | ||
| const alwaysAuth = this.getScopedOption(registry.replace(/^https?:/, ''), 'always-auth') | ||
| || this.getOption('always-auth') | ||
| || removePrefix(requestUrl, registry)[0] === '@'; | ||
| const alwaysAuth = this.getRegistryOrGlobalOption(registry, 'always-auth'); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bestander does it make sense to force adding auth key to resoled url? |
||
|
|
||
| const headers = {}; | ||
| if (this.token || (alwaysAuth && isRequestToRegistry(requestUrl, registry))) { | ||
| const authorization = this.getAuth(pathname); | ||
| const authorization = this.getAuth(packageName || pathname); | ||
| if (authorization) { | ||
| headers.authorization = authorization; | ||
| } | ||
|
|
@@ -152,15 +152,15 @@ export default class NpmRegistry extends Registry { | |
| const availableRegistries = this.getAvailableRegistries(); | ||
| const registry = availableRegistries.find((registry) => packageName.startsWith(registry)); | ||
| if (registry) { | ||
| return registry; | ||
| return addSuffix(registry, '/'); | ||
| } | ||
| } | ||
|
|
||
| for (const scope of [this.getScope(packageName), '']) { | ||
| const registry = this.getScopedOption(scope, 'registry') | ||
| || this.registries.yarn.getScopedOption(scope, 'registry'); | ||
| if (registry) { | ||
| return String(registry); | ||
| return addSuffix(String(registry), '/'); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -172,28 +172,26 @@ export default class NpmRegistry extends Registry { | |
| return this.token; | ||
| } | ||
|
|
||
| for (let registry of [this.getRegistry(packageName), '', DEFAULT_REGISTRY]) { | ||
| registry = registry.replace(/^https?:/, ''); | ||
| const registry = this.getRegistry(packageName); | ||
|
|
||
| // Check for bearer token. | ||
| let auth = this.getScopedOption(registry.replace(/\/?$/, '/'), '_authToken'); | ||
| if (auth) { | ||
| return `Bearer ${String(auth)}`; | ||
| } | ||
| // Check for bearer token. | ||
| const authToken = this.getRegistryOrGlobalOption(registry, '_authToken'); | ||
| if (authToken) { | ||
| return `Bearer ${String(authToken)}`; | ||
| } | ||
|
|
||
| // Check for basic auth token. | ||
| auth = this.getScopedOption(registry, '_auth'); | ||
| if (auth) { | ||
| return `Basic ${String(auth)}`; | ||
| } | ||
| // Check for basic auth token. | ||
| const auth = this.getRegistryOrGlobalOption(registry, '_auth'); | ||
| if (auth) { | ||
| return `Basic ${String(auth)}`; | ||
| } | ||
|
|
||
| // Check for basic username/password auth. | ||
| const username = this.getScopedOption(registry, 'username'); | ||
| const password = this.getScopedOption(registry, '_password'); | ||
| if (username && password) { | ||
| const pw = new Buffer(String(password), 'base64').toString(); | ||
| return 'Basic ' + new Buffer(String(username) + ':' + pw).toString('base64'); | ||
| } | ||
| // Check for basic username/password auth. | ||
| const username = this.getRegistryOrGlobalOption(registry, 'username'); | ||
| const password = this.getRegistryOrGlobalOption(registry, '_password'); | ||
| if (username && password) { | ||
| const pw = new Buffer(String(password), 'base64').toString(); | ||
| return 'Basic ' + new Buffer(String(username) + ':' + pw).toString('base64'); | ||
| } | ||
|
|
||
| return ''; | ||
|
|
@@ -202,4 +200,23 @@ export default class NpmRegistry extends Registry { | |
| getScopedOption(scope: string, option: string): mixed { | ||
| return this.getOption(scope + (scope ? ':' : '') + option); | ||
| } | ||
|
|
||
| getRegistryOption(registry: string, option: string): mixed { | ||
| const pre = REGEX_REGISTRY_PREFIX; | ||
| const suf = REGEX_REGISTRY_SUFFIX; | ||
|
|
||
| // When registry is used config scope, the trailing '/' is required | ||
| const reg = addSuffix(registry, '/'); | ||
|
|
||
| // 1st attempt, try to get option for the given registry URL | ||
| // 2nd attempt, remove the 'https?:' prefix of the registry URL | ||
| // 3nd attempt, remove the 'registry/?' suffix of the registry URL | ||
| return this.getScopedOption(reg, option) | ||
| || reg.match(pre) && this.getRegistryOption(reg.replace(pre, ''), option) | ||
| || reg.match(suf) && this.getRegistryOption(reg.replace(suf, ''), option); | ||
| } | ||
|
|
||
| getRegistryOrGlobalOption(registry: string, option: string): mixed { | ||
| return this.getRegistryOption(registry, option) || this.getOption(option); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it mean that requests get slower after this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also can you add a test here for the supported case?