github.com/aliyun/aliyun-oss-go-sdk@v3.0.2+incompatible/oss/error.go (about)

     1  package oss
     2  
     3  import (
     4  	"encoding/xml"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"strconv"
     9  	"strings"
    10  )
    11  
    12  // ServiceError contains fields of the error response from Oss Service REST API.
    13  type ServiceError struct {
    14  	XMLName    xml.Name `xml:"Error"`
    15  	Code       string   `xml:"Code"`      // The error code returned from OSS to the caller
    16  	Message    string   `xml:"Message"`   // The detail error message from OSS
    17  	RequestID  string   `xml:"RequestId"` // The UUID used to uniquely identify the request
    18  	HostID     string   `xml:"HostId"`    // The OSS server cluster's Id
    19  	Endpoint   string   `xml:"Endpoint"`
    20  	Ec         string   `xml:"EC"`
    21  	RawMessage string   // The raw messages from OSS
    22  	StatusCode int      // HTTP status code
    23  
    24  }
    25  
    26  // Error implements interface error
    27  func (e ServiceError) Error() string {
    28  	errorStr := fmt.Sprintf("oss: service returned error: StatusCode=%d, ErrorCode=%s, ErrorMessage=\"%s\", RequestId=%s", e.StatusCode, e.Code, e.Message, e.RequestID)
    29  	if len(e.Endpoint) > 0 {
    30  		errorStr = fmt.Sprintf("%s, Endpoint=%s", errorStr, e.Endpoint)
    31  	}
    32  	if len(e.Ec) > 0 {
    33  		errorStr = fmt.Sprintf("%s, Ec=%s", errorStr, e.Ec)
    34  	}
    35  	return errorStr
    36  }
    37  
    38  // UnexpectedStatusCodeError is returned when a storage service responds with neither an error
    39  // nor with an HTTP status code indicating success.
    40  type UnexpectedStatusCodeError struct {
    41  	allowed []int // The expected HTTP stats code returned from OSS
    42  	got     int   // The actual HTTP status code from OSS
    43  }
    44  
    45  // Error implements interface error
    46  func (e UnexpectedStatusCodeError) Error() string {
    47  	s := func(i int) string { return fmt.Sprintf("%d %s", i, http.StatusText(i)) }
    48  
    49  	got := s(e.got)
    50  	expected := []string{}
    51  	for _, v := range e.allowed {
    52  		expected = append(expected, s(v))
    53  	}
    54  	return fmt.Sprintf("oss: status code from service response is %s; was expecting %s",
    55  		got, strings.Join(expected, " or "))
    56  }
    57  
    58  // Got is the actual status code returned by oss.
    59  func (e UnexpectedStatusCodeError) Got() int {
    60  	return e.got
    61  }
    62  
    63  // CheckRespCode returns UnexpectedStatusError if the given response code is not
    64  // one of the allowed status codes; otherwise nil.
    65  func CheckRespCode(respCode int, allowed []int) error {
    66  	for _, v := range allowed {
    67  		if respCode == v {
    68  			return nil
    69  		}
    70  	}
    71  	return UnexpectedStatusCodeError{allowed, respCode}
    72  }
    73  
    74  // CheckCallbackResp return error if the given response code is not 200
    75  func CheckCallbackResp(resp *Response) error {
    76  	var err error
    77  	contentLengthStr := resp.Headers.Get("Content-Length")
    78  	contentLength, _ := strconv.Atoi(contentLengthStr)
    79  	var bodyBytes []byte
    80  	if contentLength > 0 {
    81  		bodyBytes, _ = ioutil.ReadAll(resp.Body)
    82  	}
    83  	if len(bodyBytes) > 0 {
    84  		srvErr, errIn := serviceErrFromXML(bodyBytes, resp.StatusCode,
    85  			resp.Headers.Get(HTTPHeaderOssRequestID))
    86  		if errIn != nil {
    87  			if len(resp.Headers.Get(HTTPHeaderOssEc)) > 0 {
    88  				err = fmt.Errorf("unknown response body, status code = %d, RequestId = %s, ec = %s", resp.StatusCode, resp.Headers.Get(HTTPHeaderOssRequestID), resp.Headers.Get(HTTPHeaderOssEc))
    89  			} else {
    90  				err = fmt.Errorf("unknown response body, status code= %d, RequestId = %s", resp.StatusCode, resp.Headers.Get(HTTPHeaderOssRequestID))
    91  			}
    92  		} else {
    93  			err = srvErr
    94  		}
    95  	}
    96  	return err
    97  }
    98  
    99  func tryConvertServiceError(data []byte, resp *Response, def error) (err error) {
   100  	err = def
   101  	if len(data) > 0 {
   102  		srvErr, errIn := serviceErrFromXML(data, resp.StatusCode, resp.Headers.Get(HTTPHeaderOssRequestID))
   103  		if errIn == nil {
   104  			err = srvErr
   105  		}
   106  	}
   107  	return err
   108  }
   109  
   110  // CRCCheckError is returned when crc check is inconsistent between client and server
   111  type CRCCheckError struct {
   112  	clientCRC uint64 // Calculated CRC64 in client
   113  	serverCRC uint64 // Calculated CRC64 in server
   114  	operation string // Upload operations such as PutObject/AppendObject/UploadPart, etc
   115  	requestID string // The request id of this operation
   116  }
   117  
   118  // Error implements interface error
   119  func (e CRCCheckError) Error() string {
   120  	return fmt.Sprintf("oss: the crc of %s is inconsistent, client %d but server %d; request id is %s",
   121  		e.operation, e.clientCRC, e.serverCRC, e.requestID)
   122  }
   123  
   124  func CheckDownloadCRC(clientCRC, serverCRC uint64) error {
   125  	if clientCRC == serverCRC {
   126  		return nil
   127  	}
   128  	return CRCCheckError{clientCRC, serverCRC, "DownloadFile", ""}
   129  }
   130  
   131  func CheckCRC(resp *Response, operation string) error {
   132  	if resp.Headers.Get(HTTPHeaderOssCRC64) == "" || resp.ClientCRC == resp.ServerCRC {
   133  		return nil
   134  	}
   135  	return CRCCheckError{resp.ClientCRC, resp.ServerCRC, operation, resp.Headers.Get(HTTPHeaderOssRequestID)}
   136  }