@@ -571,7 +571,7 @@ func (h *handler) renderManifest(w http.ResponseWriter, r *http.Request, image s
571571 return nil
572572}
573573
574- func (h * handler ) tagHistory (w http.ResponseWriter , r * http.Request , ref name.Reference , u string ) ([]byte , error ) {
574+ func (h * handler ) tagHistory (w http.ResponseWriter , r * http.Request , ref name.Reference , u string ) ([]byte , string , error ) {
575575 repo := ref .Context ().String ()
576576
577577 auth := authn .Anonymous
@@ -590,27 +590,91 @@ func (h *handler) tagHistory(w http.ResponseWriter, r *http.Request, ref name.Re
590590 }
591591 tr , err := h .transportFromCookie (w , r , repo , auth )
592592 if err != nil {
593- return nil , err
593+ return nil , "" , err
594594 }
595595
596596 req , err := http .NewRequest (http .MethodGet , u , nil )
597597 if err != nil {
598- return nil , err
598+ return nil , "" , err
599599 }
600600
601601 req .Header .Set ("User-Agent" , h .userAgent )
602602
603603 resp , err := tr .RoundTrip (req )
604604 if err != nil {
605- return nil , err
605+ return nil , "" , err
606606 }
607607 defer resp .Body .Close ()
608608
609609 if resp .StatusCode != http .StatusOK {
610- return nil , fmt .Errorf ("unexpected status: %d" , resp .StatusCode )
610+ return nil , "" , fmt .Errorf ("unexpected status: %d" , resp .StatusCode )
611+ }
612+
613+ link := resp .Header .Get ("Link" )
614+
615+ b , err := io .ReadAll (resp .Body )
616+ if err != nil {
617+ return nil , "" , err
611618 }
612619
613- return io .ReadAll (resp .Body )
620+ return b , link , nil
621+ }
622+
623+ func (h * handler ) renderLinks (w http.ResponseWriter , r * http.Request , links , u string ) error {
624+ if links == "" {
625+ return nil
626+ }
627+
628+ uri , err := url .Parse (u )
629+ if err != nil {
630+ return err
631+ }
632+
633+ fmt .Fprintf (w , "<p>Link: " )
634+ for i , link := range strings .Split (links , "," ) {
635+ clean := strings .TrimSpace (link )
636+ if ! strings .HasPrefix (clean , "<" ) {
637+ continue
638+ }
639+ clean = strings .TrimPrefix (clean , "<" )
640+ before , _ , ok := strings .Cut (clean , ">" )
641+ if ! ok {
642+ return fmt .Errorf ("weird link: %q" , clean )
643+ }
644+ clean = before
645+ clean = strings .TrimSpace (clean )
646+
647+ log .Printf ("clean: %q" , clean )
648+
649+ relative , err := uri .Parse (clean )
650+ if err != nil {
651+ return err
652+ }
653+
654+ newUrl := * r .URL
655+
656+ q := r .URL .Query ()
657+ if start := relative .Query ().Get ("start" ); start != "" {
658+ q .Set ("start" , start )
659+ }
660+ if end := relative .Query ().Get ("end" ); end != "" {
661+ q .Set ("end" , end )
662+ }
663+ newUrl .RawQuery = q .Encode ()
664+
665+ log .Printf ("newUrl: %q" , newUrl )
666+
667+ href := fmt .Sprintf ("<a href=%q>%s</a>" , newUrl .String (), html .EscapeString (clean ))
668+ withHref := strings .Replace (link , clean , href , 1 )
669+
670+ if i > 0 {
671+ fmt .Fprintf (w , ", " )
672+ }
673+ fmt .Fprintf (w , "%s" , withHref )
674+ }
675+ fmt .Fprintf (w , "</p>" )
676+
677+ return nil
614678}
615679
616680// Render CGR history.
@@ -624,10 +688,11 @@ func (h *handler) renderHistory(w http.ResponseWriter, r *http.Request, image st
624688 return fmt .Errorf ("not a cgr.dev image: %s" , image )
625689 }
626690
627- u := fmt .Sprintf ("https://%s/v2/%s/_chainguard/history/%s" , ref .Context ().Registry , ref .Context ().RepositoryStr (), ref .Identifier ())
691+ // Make sure we are descending until I've been dead for a while.
692+ u := fmt .Sprintf ("https://%s/v2/%s/_chainguard/history/%s?end=3000-01-01T00:00:00.000Z" , ref .Context ().Registry , ref .Context ().RepositoryStr (), ref .Identifier ())
628693
629694 // TODO: Do we need to cache this?
630- th , err := h .tagHistory (w , r , ref , u )
695+ th , link , err := h .tagHistory (w , r , ref , u )
631696 if err != nil {
632697 return err
633698 }
@@ -661,6 +726,10 @@ func (h *handler) renderHistory(w http.ResponseWriter, r *http.Request, image st
661726 return fmt .Errorf ("bodyTmpl: %w" , err )
662727 }
663728
729+ if err := h .renderLinks (w , r , link , u ); err != nil {
730+ return fmt .Errorf ("renderLinks: %w" , err )
731+ }
732+
664733 if err := h .renderContent (w , r , ref , b , output , copied ); err != nil {
665734 return err
666735 }
0 commit comments