mirror of
https://github.com/moby/moby.git
synced 2026-08-03 22:51:03 +00:00
client: Use containerd errdefs to convert http errors
Previously, we were using our own `FromStatusCode` function to map HTTP status codes to Docker error types. Switch to the containerd code. Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
@@ -4,8 +4,10 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/errdefs/pkg/errhttp"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
)
|
||||
|
||||
@@ -85,3 +87,43 @@ func (cli *Client) NewVersionError(ctx context.Context, APIrequired, feature str
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type httpError struct {
|
||||
err error
|
||||
errdef error
|
||||
}
|
||||
|
||||
func (e *httpError) Error() string {
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
func (e *httpError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
func (e *httpError) Is(target error) bool {
|
||||
return errors.Is(e.errdef, target)
|
||||
}
|
||||
|
||||
// httpErrorFromStatusCode creates an errdef error, based on the provided HTTP status-code
|
||||
func httpErrorFromStatusCode(err error, statusCode int) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
base := errhttp.ToNative(statusCode)
|
||||
if base != nil {
|
||||
return &httpError{err: err, errdef: base}
|
||||
}
|
||||
|
||||
switch {
|
||||
case statusCode >= http.StatusOK && statusCode < http.StatusBadRequest:
|
||||
// it's a client error
|
||||
return err
|
||||
case statusCode >= http.StatusBadRequest && statusCode < http.StatusInternalServerError:
|
||||
return &httpError{err: err, errdef: cerrdefs.ErrInvalidArgument}
|
||||
case statusCode >= http.StatusInternalServerError && statusCode < 600:
|
||||
return &httpError{err: err, errdef: cerrdefs.ErrInternal}
|
||||
default:
|
||||
return &httpError{err: err, errdef: cerrdefs.ErrUnknown}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -197,7 +196,7 @@ func (cli *Client) checkResponseErr(serverResp *http.Response) (retErr error) {
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
retErr = errdefs.FromStatusCode(retErr, serverResp.StatusCode)
|
||||
retErr = httpErrorFromStatusCode(retErr, serverResp.StatusCode)
|
||||
}()
|
||||
|
||||
var body []byte
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
)
|
||||
|
||||
// FromStatusCode creates an errdef error, based on the provided HTTP status-code
|
||||
//
|
||||
// Deprecated: Use [cerrdefs.ToNative] instead
|
||||
func FromStatusCode(err error, statusCode int) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
|
||||
@@ -83,6 +83,7 @@ func TestFromStatusCode(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(http.StatusText(tc.status), func(t *testing.T) {
|
||||
//nolint:staticcheck // ignore SA1019: FromStatusCode is deprecated
|
||||
err := FromStatusCode(tc.err, tc.status)
|
||||
if !tc.check(err) {
|
||||
t.Errorf("unexpected error-type %T", err)
|
||||
|
||||
@@ -30,6 +30,7 @@ require (
|
||||
github.com/containerd/containerd/v2 v2.0.5
|
||||
github.com/containerd/continuity v0.4.5
|
||||
github.com/containerd/errdefs v1.0.0
|
||||
github.com/containerd/errdefs/pkg v0.3.0
|
||||
github.com/containerd/fifo v1.1.0
|
||||
github.com/containerd/log v0.1.0
|
||||
github.com/containerd/platforms v1.0.0-rc.1
|
||||
@@ -148,7 +149,6 @@ require (
|
||||
github.com/container-storage-interface/spec v1.5.0 // indirect
|
||||
github.com/containerd/accelerated-container-image v1.3.0 // indirect
|
||||
github.com/containerd/console v1.0.4 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/go-cni v1.1.12 // indirect
|
||||
github.com/containerd/go-runc v1.1.0 // indirect
|
||||
github.com/containerd/nydus-snapshotter v0.15.0 // indirect
|
||||
|
||||
96
vendor/github.com/containerd/errdefs/pkg/errhttp/http.go
generated
vendored
Normal file
96
vendor/github.com/containerd/errdefs/pkg/errhttp/http.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package errhttp provides utility functions for translating errors to
|
||||
// and from a HTTP context.
|
||||
//
|
||||
// The functions ToHTTP and ToNative can be used to map server-side and
|
||||
// client-side errors to the correct types.
|
||||
package errhttp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/containerd/errdefs"
|
||||
"github.com/containerd/errdefs/pkg/internal/cause"
|
||||
)
|
||||
|
||||
// ToHTTP returns the best status code for the given error
|
||||
func ToHTTP(err error) int {
|
||||
switch {
|
||||
case errdefs.IsNotFound(err):
|
||||
return http.StatusNotFound
|
||||
case errdefs.IsInvalidArgument(err):
|
||||
return http.StatusBadRequest
|
||||
case errdefs.IsConflict(err):
|
||||
return http.StatusConflict
|
||||
case errdefs.IsNotModified(err):
|
||||
return http.StatusNotModified
|
||||
case errdefs.IsFailedPrecondition(err):
|
||||
return http.StatusPreconditionFailed
|
||||
case errdefs.IsUnauthorized(err):
|
||||
return http.StatusUnauthorized
|
||||
case errdefs.IsPermissionDenied(err):
|
||||
return http.StatusForbidden
|
||||
case errdefs.IsResourceExhausted(err):
|
||||
return http.StatusTooManyRequests
|
||||
case errdefs.IsInternal(err):
|
||||
return http.StatusInternalServerError
|
||||
case errdefs.IsNotImplemented(err):
|
||||
return http.StatusNotImplemented
|
||||
case errdefs.IsUnavailable(err):
|
||||
return http.StatusServiceUnavailable
|
||||
case errdefs.IsUnknown(err):
|
||||
var unexpected cause.ErrUnexpectedStatus
|
||||
if errors.As(err, &unexpected) && unexpected.Status >= 200 && unexpected.Status < 600 {
|
||||
return unexpected.Status
|
||||
}
|
||||
return http.StatusInternalServerError
|
||||
default:
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
}
|
||||
|
||||
// ToNative returns the error best matching the HTTP status code
|
||||
func ToNative(statusCode int) error {
|
||||
switch statusCode {
|
||||
case http.StatusNotFound:
|
||||
return errdefs.ErrNotFound
|
||||
case http.StatusBadRequest:
|
||||
return errdefs.ErrInvalidArgument
|
||||
case http.StatusConflict:
|
||||
return errdefs.ErrConflict
|
||||
case http.StatusPreconditionFailed:
|
||||
return errdefs.ErrFailedPrecondition
|
||||
case http.StatusUnauthorized:
|
||||
return errdefs.ErrUnauthenticated
|
||||
case http.StatusForbidden:
|
||||
return errdefs.ErrPermissionDenied
|
||||
case http.StatusNotModified:
|
||||
return errdefs.ErrNotModified
|
||||
case http.StatusTooManyRequests:
|
||||
return errdefs.ErrResourceExhausted
|
||||
case http.StatusInternalServerError:
|
||||
return errdefs.ErrInternal
|
||||
case http.StatusNotImplemented:
|
||||
return errdefs.ErrNotImplemented
|
||||
case http.StatusServiceUnavailable:
|
||||
return errdefs.ErrUnavailable
|
||||
default:
|
||||
return cause.ErrUnexpectedStatus{Status: statusCode}
|
||||
}
|
||||
}
|
||||
1
vendor/modules.txt
vendored
1
vendor/modules.txt
vendored
@@ -420,6 +420,7 @@ github.com/containerd/errdefs
|
||||
# github.com/containerd/errdefs/pkg v0.3.0
|
||||
## explicit; go 1.22
|
||||
github.com/containerd/errdefs/pkg/errgrpc
|
||||
github.com/containerd/errdefs/pkg/errhttp
|
||||
github.com/containerd/errdefs/pkg/internal/cause
|
||||
github.com/containerd/errdefs/pkg/internal/types
|
||||
# github.com/containerd/fifo v1.1.0
|
||||
|
||||
Reference in New Issue
Block a user