@@ -330,7 +330,7 @@ v2Router.delete("/:name+/blobs/uploads/:id", async (req, env: Env) => {
330330
331331// this is the first thing that the client asks for in an upload
332332v2Router . post ( "/:name+/blobs/uploads/" , async ( req , env : Env ) => {
333- const { name } = req . params ;
333+ const { name } = req . params ;
334334 const [ uploadObject , err ] = await wrap < UploadObject | RegistryError , Error > ( env . REGISTRY_CLIENT . startUpload ( name ) ) ;
335335
336336 if ( err ) {
@@ -525,31 +525,49 @@ v2Router.get("/:name+/tags/list", async (req, env: Env) => {
525525
526526 const { n : nStr = 50 , last } = req . query ;
527527 const n = + nStr ;
528- if ( isNaN ( n ) ) {
528+ if ( isNaN ( n ) || n <= 0 ) {
529529 throw new ServerError ( "invalid 'n' parameter" , 400 ) ;
530530 }
531531
532- const tags = await env . REGISTRY . list ( {
532+ let tags = await env . REGISTRY . list ( {
533533 prefix : `${ name } /manifests` ,
534534 limit : n ,
535535 startAfter : last ? `${ name } /manifests/${ last } ` : undefined ,
536536 } ) ;
537+ // Filter out sha256 manifest
538+ let manifestTags = tags . objects . filter ( ( tag ) => ! tag . key . startsWith ( `${ name } /manifests/sha256:` ) ) ;
539+ // If results are truncated and the manifest filter removed some result, extend the search to reach the n number of results expected by the client
540+ while ( tags . objects . length > 0 && tags . truncated && manifestTags . length !== n ) {
541+ tags = await env . REGISTRY . list ( {
542+ prefix : `${ name } /manifests` ,
543+ limit : n - manifestTags . length ,
544+ cursor : tags . cursor ,
545+ } ) ;
546+ // Filter out sha256 manifest
547+ manifestTags = manifestTags . concat (
548+ tags . objects . filter ( ( tag ) => ! tag . key . startsWith ( `${ name } /manifests/sha256:` ) ) ,
549+ ) ;
550+ }
537551
538- const keys = tags . objects . map ( ( object ) => object . key . split ( "/" ) . pop ( ) ! ) ;
552+ const keys = manifestTags . map ( ( object ) => object . key . split ( "/" ) . pop ( ) ! ) ;
539553 const url = new URL ( req . url ) ;
540554 url . searchParams . set ( "n" , `${ n } ` ) ;
541555 url . searchParams . set ( "last" , keys . length ? keys [ keys . length - 1 ] : "" ) ;
556+ const responseHeaders : { "Content-Type" : string ; "Link" ?: string } = {
557+ "Content-Type" : "application/json" ,
558+ } ;
559+ // Only supply a next link if the previous result is truncated
560+ if ( tags . truncated ) {
561+ responseHeaders . Link = `${ url . toString ( ) } ; rel=next` ;
562+ }
542563 return new Response (
543564 JSON . stringify ( {
544565 name,
545566 tags : keys ,
546567 } ) ,
547568 {
548569 status : 200 ,
549- headers : {
550- "Content-Type" : "application/json" ,
551- "Link" : `${ url . toString ( ) } ; rel=next` ,
552- } ,
570+ headers : responseHeaders ,
553571 } ,
554572 ) ;
555573} ) ;
0 commit comments