@@ -9,7 +9,7 @@ import * as fs from '../util/fs.js';
99import NpmResolver from '../resolvers/registries/npm-resolver.js' ;
1010import envReplace from '../util/env-replace.js' ;
1111import Registry from './base-registry.js' ;
12- import { addSuffix , removePrefix } from '../util/misc' ;
12+ import { addSuffix } from '../util/misc' ;
1313import isRequestToRegistry from './is-request-to-registry.js' ;
1414
1515const userHome = require ( '../util/user-home-dir' ) . default ;
@@ -18,6 +18,8 @@ const url = require('url');
1818const ini = require ( 'ini' ) ;
1919
2020const DEFAULT_REGISTRY = 'https://registry.npmjs.org/' ;
21+ const REGEX_REGISTRY_PREFIX = / ^ h t t p s ? : / ;
22+ const REGEX_REGISTRY_SUFFIX = / r e g i s t r y \/ ? $ / ;
2123
2224function getGlobalPrefix ( ) : string {
2325 if ( process . env . PREFIX ) {
@@ -51,18 +53,17 @@ export default class NpmRegistry extends Registry {
5153 return name . replace ( '/' , '%2f' ) ;
5254 }
5355
54- request ( pathname : string , opts ?: RegistryRequestOptions = { } ) : Promise < * > {
55- const registry = addSuffix ( this . getRegistry ( pathname ) , '/' ) ;
56+ request ( pathname : string , opts ?: RegistryRequestOptions = { } , packageName : ? string ) : Promise < * > {
57+ const registry = this . getRegistry ( packageName || pathname ) ;
5658 const requestUrl = url . resolve ( registry , pathname ) ;
57- const alwaysAuth = this . getScopedOption ( registry . replace ( / ^ h t t p s ? : / , '' ) , 'always-auth' )
58- || this . getOption ( 'always-auth' )
59- || removePrefix ( requestUrl , registry ) [ 0 ] === '@' ;
59+ const alwaysAuth = this . getRegistryOrGlobalOption ( registry , 'always-auth' ) ;
60+ const customHostSuffix = this . getRegistryOrGlobalOption ( registry , 'custom-host-suffix' ) ;
6061
6162 const headers = Object . assign ( {
6263 'Accept' : 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*' ,
6364 } , opts . headers ) ;
64- if ( this . token || ( alwaysAuth && isRequestToRegistry ( requestUrl , registry ) ) ) {
65- const authorization = this . getAuth ( pathname ) ;
65+ if ( this . token || ( alwaysAuth && isRequestToRegistry ( requestUrl , registry , customHostSuffix ) ) ) {
66+ const authorization = this . getAuth ( packageName || pathname ) ;
6667 if ( authorization ) {
6768 headers . authorization = authorization ;
6869 }
@@ -160,15 +161,15 @@ export default class NpmRegistry extends Registry {
160161 const availableRegistries = this . getAvailableRegistries ( ) ;
161162 const registry = availableRegistries . find ( ( registry ) => packageName . startsWith ( registry ) ) ;
162163 if ( registry ) {
163- return registry ;
164+ return addSuffix ( registry , '/' ) ;
164165 }
165166 }
166167
167168 for ( const scope of [ this . getScope ( packageName ) , '' ] ) {
168169 const registry = this . getScopedOption ( scope , 'registry' )
169170 || this . registries . yarn . getScopedOption ( scope , 'registry' ) ;
170171 if ( registry ) {
171- return String ( registry ) ;
172+ return addSuffix ( String ( registry ) , '/' ) ;
172173 }
173174 }
174175
@@ -180,28 +181,26 @@ export default class NpmRegistry extends Registry {
180181 return this . token ;
181182 }
182183
183- for ( let registry of [ this . getRegistry ( packageName ) , '' , DEFAULT_REGISTRY ] ) {
184- registry = registry . replace ( / ^ h t t p s ? : / , '' ) ;
184+ const registry = this . getRegistry ( packageName ) ;
185185
186- // Check for bearer token.
187- let auth = this . getScopedOption ( registry . replace ( / \/ ? $ / , '/' ) , '_authToken' ) ;
188- if ( auth ) {
189- return `Bearer ${String ( auth ) } `;
190- }
186+ // Check for bearer token.
187+ const authToken = this . getRegistryOrGlobalOption ( registry , '_authToken' ) ;
188+ if ( authToken ) {
189+ return `Bearer ${String ( authToken ) } `;
190+ }
191191
192- // Check for basic auth token.
193- auth = this.getScopedOption (registry, '_auth');
194- if (auth) {
195- return ` Basic ${String ( auth ) } `;
196- }
192+ // Check for basic auth token.
193+ const auth = this.getRegistryOrGlobalOption (registry, '_auth');
194+ if (auth) {
195+ return ` Basic ${String ( auth ) } `;
196+ }
197197
198- // Check for basic username/password auth.
199- const username = this . getScopedOption ( registry , 'username' ) ;
200- const password = this . getScopedOption ( registry , '_password' ) ;
201- if ( username && password ) {
202- const pw = new Buffer ( String ( password ) , 'base64' ) . toString ( ) ;
203- return 'Basic ' + new Buffer ( String ( username ) + ':' + pw ) . toString ( 'base64' ) ;
204- }
198+ // Check for basic username/password auth.
199+ const username = this . getRegistryOrGlobalOption ( registry , 'username' ) ;
200+ const password = this . getRegistryOrGlobalOption ( registry , '_password' ) ;
201+ if ( username && password ) {
202+ const pw = new Buffer ( String ( password ) , 'base64' ) . toString ( ) ;
203+ return 'Basic ' + new Buffer ( String ( username ) + ':' + pw ) . toString ( 'base64' ) ;
205204 }
206205
207206 return '' ;
@@ -210,4 +209,23 @@ export default class NpmRegistry extends Registry {
210209 getScopedOption ( scope : string , option : string ) : mixed {
211210 return this . getOption ( scope + ( scope ? ':' : '' ) + option ) ;
212211 }
212+
213+ getRegistryOption ( registry : string , option : string ) : mixed {
214+ const pre = REGEX_REGISTRY_PREFIX ;
215+ const suf = REGEX_REGISTRY_SUFFIX ;
216+
217+ // When registry is used config scope, the trailing '/' is required
218+ const reg = addSuffix ( registry , '/' ) ;
219+
220+ // 1st attempt, try to get option for the given registry URL
221+ // 2nd attempt, remove the 'https?:' prefix of the registry URL
222+ // 3nd attempt, remove the 'registry/?' suffix of the registry URL
223+ return this . getScopedOption ( reg , option )
224+ || reg . match ( pre ) && this . getRegistryOption ( reg . replace ( pre , '' ) , option )
225+ || reg . match ( suf ) && this . getRegistryOption ( reg . replace ( suf , '' ) , option ) ;
226+ }
227+
228+ getRegistryOrGlobalOption ( registry : string , option : string ) : mixed {
229+ return this . getRegistryOption ( registry , option ) || this . getOption ( option ) ;
230+ }
213231}
0 commit comments