@@ -13,6 +13,7 @@ import (
1313 "regexp"
1414 "strconv"
1515 "strings"
16+ "sync"
1617
1718 auth_model "code.gitea.io/gitea/models/auth"
1819 packages_model "code.gitea.io/gitea/models/packages"
@@ -39,10 +40,14 @@ import (
3940// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-manifests
4041const maxManifestSize = 10 * 1024 * 1024
4142
42- var (
43- imageNamePattern = regexp .MustCompile (`\A[a-z0-9]+([._-][a-z0-9]+)*(/[a-z0-9]+([._-][a-z0-9]+)*)*\z` )
44- referencePattern = regexp .MustCompile (`\A[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}\z` )
45- )
43+ var globalVars = sync .OnceValue (func () (ret struct {
44+ imageNamePattern , referencePattern * regexp.Regexp
45+ },
46+ ) {
47+ ret .imageNamePattern = regexp .MustCompile (`\A[a-z0-9]+([._-][a-z0-9]+)*(/[a-z0-9]+([._-][a-z0-9]+)*)*\z` )
48+ ret .referencePattern = regexp .MustCompile (`\A[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}\z` )
49+ return ret
50+ })
4651
4752type containerHeaders struct {
4853 Status int
@@ -84,9 +89,7 @@ func jsonResponse(ctx *context.Context, status int, obj any) {
8489 Status : status ,
8590 ContentType : "application/json" ,
8691 })
87- if err := json .NewEncoder (ctx .Resp ).Encode (obj ); err != nil {
88- log .Error ("JSON encode: %v" , err )
89- }
92+ _ = json .NewEncoder (ctx .Resp ).Encode (obj ) // ignore network errors
9093}
9194
9295func apiError (ctx * context.Context , status int , err error ) {
@@ -134,7 +137,7 @@ func ReqContainerAccess(ctx *context.Context) {
134137
135138// VerifyImageName is a middleware which checks if the image name is allowed
136139func VerifyImageName (ctx * context.Context ) {
137- if ! imageNamePattern .MatchString (ctx .PathParam ("image" )) {
140+ if ! globalVars (). imageNamePattern .MatchString (ctx .PathParam ("image" )) {
138141 apiErrorDefined (ctx , errNameInvalid )
139142 }
140143}
@@ -216,7 +219,7 @@ func GetRepositoryList(ctx *context.Context) {
216219 if len (repositories ) == n {
217220 v := url.Values {}
218221 if n > 0 {
219- v .Add ("n" , strconv .Itoa (n ))
222+ v .Add ("n" , strconv .Itoa (n )) // FIXME: "n" can't be zero here, the logic is inconsistent with GetTagsList
220223 }
221224 v .Add ("last" , repositories [len (repositories )- 1 ])
222225
@@ -565,7 +568,7 @@ func PutManifest(ctx *context.Context) {
565568 IsTagged : digest .Digest (reference ).Validate () != nil ,
566569 }
567570
568- if mci .IsTagged && ! referencePattern .MatchString (reference ) {
571+ if mci .IsTagged && ! globalVars (). referencePattern .MatchString (reference ) {
569572 apiErrorDefined (ctx , errManifestInvalid .WithMessage ("Tag is invalid" ))
570573 return
571574 }
@@ -618,7 +621,7 @@ func getBlobSearchOptionsFromContext(ctx *context.Context) (*container_model.Blo
618621 reference := ctx .PathParam ("reference" )
619622 if d := digest .Digest (reference ); d .Validate () == nil {
620623 opts .Digest = string (d )
621- } else if referencePattern .MatchString (reference ) {
624+ } else if globalVars (). referencePattern .MatchString (reference ) {
622625 opts .Tag = reference
623626 opts .OnlyLead = true
624627 } else {
@@ -782,7 +785,8 @@ func GetTagsList(ctx *context.Context) {
782785 })
783786}
784787
785- // FIXME: Workaround to be removed in v1.20
788+ // FIXME: Workaround to be removed in v1.20.
789+ // Update maybe we should never really remote it, as long as there is legacy data?
786790// https://github.com/go-gitea/gitea/issues/19586
787791func workaroundGetContainerBlob (ctx * context.Context , opts * container_model.BlobSearchOptions ) (* packages_model.PackageFileDescriptor , error ) {
788792 blob , err := container_model .GetContainerBlob (ctx , opts )
0 commit comments