docker-distribution/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go

73 lines
1.9 KiB
Go

//go:build go1.18
// +build go1.18
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package runtime
import (
"fmt"
"net/http"
"strings"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo"
)
// bodyDownloadPolicy creates a policy object that downloads the response's body to a []byte.
func bodyDownloadPolicy(req *policy.Request) (*http.Response, error) {
resp, err := req.Next()
if err != nil {
return resp, err
}
var opValues bodyDownloadPolicyOpValues
// don't skip downloading error response bodies
if req.OperationValue(&opValues); opValues.Skip && resp.StatusCode < 400 {
return resp, err
}
// Either bodyDownloadPolicyOpValues was not specified (so skip is false)
// or it was specified and skip is false: don't skip downloading the body
_, err = Payload(resp)
if err != nil {
return resp, newBodyDownloadError(err, req)
}
return resp, err
}
// bodyDownloadPolicyOpValues is the struct containing the per-operation values
type bodyDownloadPolicyOpValues struct {
Skip bool
}
type bodyDownloadError struct {
err error
}
func newBodyDownloadError(err error, req *policy.Request) error {
// on failure, only retry the request for idempotent operations.
// we currently identify them as DELETE, GET, and PUT requests.
if m := strings.ToUpper(req.Raw().Method); m == http.MethodDelete || m == http.MethodGet || m == http.MethodPut {
// error is safe for retry
return err
}
// wrap error to avoid retries
return &bodyDownloadError{
err: err,
}
}
func (b *bodyDownloadError) Error() string {
return fmt.Sprintf("body download policy: %s", b.err.Error())
}
func (b *bodyDownloadError) NonRetriable() {
// marker method
}
func (b *bodyDownloadError) Unwrap() error {
return b.err
}
var _ errorinfo.NonRetriable = (*bodyDownloadError)(nil)