fix: if reference exceeds the threshold return 400 and detail

If the reference in the API request exceeds the threshold allowed by the
reference package (NOTE: this isn't defined by distribution
specification!) we return 500 back to the client.

This commit makes sure we return 400 and the explanation of the error in
the returned JSON payload.

Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
This commit is contained in:
Milos Gajdos 2023-11-22 16:06:33 +00:00
parent 96582fcfd9
commit 35abc92237
No known key found for this signature in database
3 changed files with 23 additions and 2 deletions

View file

@ -224,11 +224,20 @@ func (errs Errors) MarshalJSON() ([]byte, error) {
msg = err.Code.Message() msg = err.Code.Message()
} }
tmpErrs.Errors = append(tmpErrs.Errors, Error{ tmpErr := Error{
Code: err.Code, Code: err.Code,
Message: msg, Message: msg,
Detail: err.Detail, Detail: err.Detail,
}) }
// if the detail contains error extract the error message
// otherwise json.Marshal will not serialize it at all
// https://github.com/golang/go/issues/10748
if detail, ok := tmpErr.Detail.(error); ok {
tmpErr.Detail = detail.Error()
}
tmpErrs.Errors = append(tmpErrs.Errors, tmpErr)
} }
return json.Marshal(tmpErrs) return json.Marshal(tmpErrs)

View file

@ -47,6 +47,12 @@ func NewInMemoryBlobDescriptorCacheProvider(size int) cache.BlobDescriptorCacheP
func (imbdcp *inMemoryBlobDescriptorCacheProvider) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) { func (imbdcp *inMemoryBlobDescriptorCacheProvider) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) {
if _, err := reference.ParseNormalizedNamed(repo); err != nil { if _, err := reference.ParseNormalizedNamed(repo); err != nil {
if err == reference.ErrNameTooLong {
return nil, distribution.ErrRepositoryNameInvalid{
Name: repo,
Reason: reference.ErrNameTooLong,
}
}
return nil, err return nil, err
} }

View file

@ -50,6 +50,12 @@ func NewRedisBlobDescriptorCacheProvider(pool *redis.Client) cache.BlobDescripto
// RepositoryScoped returns the scoped cache. // RepositoryScoped returns the scoped cache.
func (rbds *redisBlobDescriptorService) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) { func (rbds *redisBlobDescriptorService) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) {
if _, err := reference.ParseNormalizedNamed(repo); err != nil { if _, err := reference.ParseNormalizedNamed(repo); err != nil {
if err == reference.ErrNameTooLong {
return nil, distribution.ErrRepositoryNameInvalid{
Name: repo,
Reason: reference.ErrNameTooLong,
}
}
return nil, err return nil, err
} }