@@ -24,6 +24,11 @@ type AuthContext = {
2424 scope : string ;
2525} ;
2626
27+ export function isDockerDotIO ( url : URL ) : boolean {
28+ const regex = / ^ h t t p s : \/ \/ ( [ \w \d ] + \. ) ? d o c k e r \. i o $ / ;
29+ return regex . test ( url . origin ) ;
30+ }
31+
2732type HTTPContext = {
2833 // The auth context for this request
2934 authContext : AuthContext ;
@@ -149,14 +154,35 @@ export class RegistryHTTPClient implements Registry {
149154 }
150155
151156 authBase64 ( ) : string {
157+ const configuration = this . configuration ;
158+ if ( configuration . username === undefined ) {
159+ return "" ;
160+ }
161+
152162 return btoa ( this . configuration . username + ":" + this . password ( ) ) ;
153163 }
154164
155165 password ( ) : string {
156- return ( this . env as unknown as Record < string , string > ) [ this . configuration . password_env ] ?? "" ;
166+ const configuration = this . configuration ;
167+ if ( configuration . username === undefined ) {
168+ return "" ;
169+ }
170+
171+ return ( this . env as unknown as Record < string , string > ) [ configuration . password_env ] ?? "" ;
157172 }
158173
159174 async authenticate ( namespace : string ) : Promise < HTTPContext > {
175+ const emptyAuthentication = {
176+ authContext : {
177+ authType : "none" ,
178+ realm : "" ,
179+ scope : "" ,
180+ service : this . url . host ,
181+ } ,
182+ repository : this . url . pathname ,
183+ accessToken : "" ,
184+ } as const ;
185+
160186 const res = await fetch ( `${ this . url . protocol } //${ this . url . host } /v2/` , {
161187 headers : {
162188 "User-Agent" : "Docker-Client/24.0.5 (linux)" ,
@@ -165,16 +191,7 @@ export class RegistryHTTPClient implements Registry {
165191 } ) ;
166192
167193 if ( res . ok ) {
168- return {
169- authContext : {
170- authType : "none" ,
171- realm : "" ,
172- scope : "" ,
173- service : this . url . host ,
174- } ,
175- repository : this . url . pathname ,
176- accessToken : "" ,
177- } ;
194+ return emptyAuthentication ;
178195 }
179196
180197 if ( res . status !== 401 ) {
@@ -212,11 +229,12 @@ export class RegistryHTTPClient implements Registry {
212229 async authenticateBearerSimple ( ctx : AuthContext , params : URLSearchParams ) : Promise < Response > {
213230 params . delete ( "password" ) ;
214231 console . log ( "sending authentication parameters:" , ctx . realm + "?" + params . toString ( ) ) ;
232+
215233 return await fetch ( ctx . realm + "?" + params . toString ( ) , {
216234 headers : {
217- "Authorization" : "Basic " + this . authBase64 ( ) ,
218235 "Accept" : "application/json" ,
219236 "User-Agent" : "Docker-Client/24.0.5 (linux)" ,
237+ ...( this . configuration . username !== undefined ? { Authorization : "Basic " + this . authBase64 ( ) } : { } ) ,
220238 } ,
221239 } ) ;
222240 }
@@ -227,8 +245,8 @@ export class RegistryHTTPClient implements Registry {
227245 // explicitely include that we don't want an offline_token.
228246 scope : `repository:${ ctx . scope } :pull,push` ,
229247 client_id : "r2registry" ,
230- grant_type : "password" ,
231- password : this . password ( ) ,
248+ grant_type : this . configuration . username === undefined ? "none" : "password" ,
249+ password : this . configuration . username === undefined ? "" : this . password ( ) ,
232250 } ) ;
233251 let response = await fetch ( ctx . realm , {
234252 headers : {
@@ -313,7 +331,7 @@ export class RegistryHTTPClient implements Registry {
313331 }
314332
315333 async manifestExists ( name : string , tag : string ) : Promise < CheckManifestResponse | RegistryError > {
316- const namespace = name . includes ( "/" ) ? name : `library/${ name } ` ;
334+ const namespace = name . includes ( "/" ) || ! isDockerDotIO ( this . url ) ? name : `library/${ name } ` ;
317335 try {
318336 const ctx = await this . authenticate ( namespace ) ;
319337 const req = ctxIntoRequest ( ctx , this . url , "HEAD" , `${ namespace } /manifests/${ tag } ` ) ;
@@ -342,7 +360,7 @@ export class RegistryHTTPClient implements Registry {
342360 }
343361
344362 async getManifest ( name : string , digest : string ) : Promise < GetManifestResponse | RegistryError > {
345- const namespace = name . includes ( "/" ) ? name : `library/${ name } ` ;
363+ const namespace = name . includes ( "/" ) || ! isDockerDotIO ( this . url ) ? name : `library/${ name } ` ;
346364 try {
347365 const ctx = await this . authenticate ( namespace ) ;
348366 const req = ctxIntoRequest ( ctx , this . url , "GET" , `${ namespace } /manifests/${ digest } ` ) ;
@@ -374,7 +392,7 @@ export class RegistryHTTPClient implements Registry {
374392 }
375393
376394 async layerExists ( name : string , digest : string ) : Promise < CheckLayerResponse | RegistryError > {
377- const namespace = name . includes ( "/" ) ? name : `library/${ name } ` ;
395+ const namespace = name . includes ( "/" ) || ! isDockerDotIO ( this . url ) ? name : `library/${ name } ` ;
378396 try {
379397 const ctx = await this . authenticate ( namespace ) ;
380398 const res = await fetch ( ctxIntoRequest ( ctx , this . url , "HEAD" , `${ namespace } /blobs/${ digest } ` ) ) ;
@@ -414,7 +432,7 @@ export class RegistryHTTPClient implements Registry {
414432 }
415433
416434 async getLayer ( name : string , digest : string ) : Promise < GetLayerResponse | RegistryError > {
417- const namespace = name . includes ( "/" ) ? name : `library/${ name } ` ;
435+ const namespace = name . includes ( "/" ) || ! isDockerDotIO ( this . url ) ? name : `library/${ name } ` ;
418436 try {
419437 const ctx = await this . authenticate ( namespace ) ;
420438 const req = ctxIntoRequest ( ctx , this . url , "GET" , `${ namespace } /blobs/${ digest } ` ) ;
@@ -468,7 +486,7 @@ export class RegistryHTTPClient implements Registry {
468486 _namespace : string ,
469487 _reference : string ,
470488 _readableStream : ReadableStream < any > ,
471- _contentType : string ,
489+ { } : { } ,
472490 ) : Promise < PutManifestResponse | RegistryError > {
473491 throw new Error ( "unimplemented" ) ;
474492 }
0 commit comments