Skip to content

Commit

Permalink
Read error information from header (#369)
Browse files Browse the repository at this point in the history
  • Loading branch information
yangzong18 authored and huiguangjun committed Mar 23, 2023
1 parent 72974c6 commit 64b34dc
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 19 deletions.
40 changes: 40 additions & 0 deletions oss/bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,46 @@ func (s *OssBucketSuite) TestGetObjectMeta(c *C) {
c.Assert(err, NotNil)
}

// TestErrorFromHeader
func (s *OssBucketSuite) TestErrorFromHeader(c *C) {
objectName := objectNamePrefix + RandStr(8)

// Put
err := s.bucket.PutObject(objectName, strings.NewReader(""))
c.Assert(err, IsNil)

_, err = s.bucket.GetObject(objectName)
c.Assert(err, IsNil)

meta, err := s.bucket.GetObjectMeta(objectName)
c.Assert(err, IsNil)
c.Assert(len(meta) > 0, Equals, true)

exist, err := s.bucket.IsObjectExist(objectName)
c.Assert(err, IsNil)
c.Assert(exist, Equals, true)
err = s.bucket.DeleteObject(objectName)
c.Assert(err, IsNil)

_, err = s.bucket.GetObject(objectName)
c.Assert(err, NotNil)
c.Assert(err.(ServiceError).Code, Equals, "NoSuchKey")
c.Assert(err.(ServiceError).Ec != "", Equals, true)
c.Assert(err.(ServiceError).RequestID != "", Equals, true)
c.Assert(err.(ServiceError).HostID != "", Equals, true)

exist, err = s.bucket.IsObjectExist(objectName)
c.Assert(err, IsNil)
c.Assert(exist, Equals, false)

_, err = s.bucket.GetObjectMeta("NotExistObject")
c.Assert(err, NotNil)
c.Assert(err.(ServiceError).Code, Equals, "NoSuchKey")
c.Assert(err.(ServiceError).Ec != "", Equals, true)
c.Assert(err.(ServiceError).RequestID != "", Equals, true)
c.Assert(err.(ServiceError).HostID != "", Equals, true)
}

// TestGetObjectDetailedMeta
func (s *OssBucketSuite) TestGetObjectDetailedMeta(c *C) {
objectName := objectNamePrefix + RandStr(8)
Expand Down
48 changes: 34 additions & 14 deletions oss/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,27 +506,37 @@ func (conn Conn) handleResponse(resp *http.Response, crc hash.Hash64) (*Response
if statusCode >= 400 && statusCode <= 505 {
// 4xx and 5xx indicate that the operation has error occurred
var respBody []byte
var errorXml []byte
respBody, err := readResponseBody(resp)
if err != nil {
return nil, err
}

if len(respBody) == 0 {
errorXml = respBody
if len(respBody) == 0 && len(resp.Header.Get(HTTPHeaderOssErr)) > 0 {
errorXml, err = base64.StdEncoding.DecodeString(resp.Header.Get(HTTPHeaderOssErr))
if err != nil {
errorXml = respBody
}
}
if len(errorXml) == 0 {
err = ServiceError{
StatusCode: statusCode,
RequestID: resp.Header.Get(HTTPHeaderOssRequestID),
Ec: resp.Header.Get(HTTPHeaderOssEc),
}
} else {
// Response contains storage service error object, unmarshal
srvErr, errIn := serviceErrFromXML(respBody, resp.StatusCode,
srvErr, errIn := serviceErrFromXML(errorXml, resp.StatusCode,
resp.Header.Get(HTTPHeaderOssRequestID))
if errIn != nil { // error unmarshaling the error response
err = fmt.Errorf("oss: service returned invalid response body, status = %s, RequestId = %s", resp.Status, resp.Header.Get(HTTPHeaderOssRequestID))
if errIn != nil { // error unmarshal the error response
if len(resp.Header.Get(HTTPHeaderOssEc)) > 0 {
err = fmt.Errorf("oss: service returned invalid response body, status = %s, RequestId = %s, ec = %s", resp.Status, resp.Header.Get(HTTPHeaderOssRequestID), resp.Header.Get(HTTPHeaderOssEc))
} else {
err = fmt.Errorf("oss: service returned invalid response body, status = %s, RequestId = %s", resp.Status, resp.Header.Get(HTTPHeaderOssRequestID))
}
} else {
err = srvErr
}
}

return &Response{
StatusCode: resp.StatusCode,
Headers: resp.Header,
Expand All @@ -544,27 +554,37 @@ func (conn Conn) handleResponse(resp *http.Response, crc hash.Hash64) (*Response
// (0,300) [308,400) [506,)
// Other extended http StatusCode
var respBody []byte
var errorXml []byte
respBody, err := readResponseBody(resp)
if err != nil {
return &Response{StatusCode: resp.StatusCode, Headers: resp.Header, Body: ioutil.NopCloser(bytes.NewReader(respBody))}, err
}

if len(respBody) == 0 {
errorXml = respBody
if len(respBody) == 0 && len(resp.Header.Get(HTTPHeaderOssErr)) > 0 {
errorXml, err = base64.StdEncoding.DecodeString(resp.Header.Get(HTTPHeaderOssErr))
if err != nil {
errorXml = respBody
}
}
if len(errorXml) == 0 {
err = ServiceError{
StatusCode: statusCode,
RequestID: resp.Header.Get(HTTPHeaderOssRequestID),
Ec: resp.Header.Get(HTTPHeaderOssEc),
}
} else {
// Response contains storage service error object, unmarshal
srvErr, errIn := serviceErrFromXML(respBody, resp.StatusCode,
srvErr, errIn := serviceErrFromXML(errorXml, resp.StatusCode,
resp.Header.Get(HTTPHeaderOssRequestID))
if errIn != nil { // error unmarshaling the error response
err = fmt.Errorf("unkown response body, status = %s, RequestId = %s", resp.Status, resp.Header.Get(HTTPHeaderOssRequestID))
if errIn != nil { // error unmarshal the error response
if len(resp.Header.Get(HTTPHeaderOssEc)) > 0 {
err = fmt.Errorf("oss: service returned invalid response body, status = %s, RequestId = %s, ec = %s", resp.Status, resp.Header.Get(HTTPHeaderOssRequestID), resp.Header.Get(HTTPHeaderOssEc))
} else {
err = fmt.Errorf("oss: service returned invalid response body, status = %s, RequestId = %s", resp.Status, resp.Header.Get(HTTPHeaderOssRequestID))
}
} else {
err = srvErr
}
}

return &Response{
StatusCode: resp.StatusCode,
Headers: resp.Header,
Expand Down
2 changes: 2 additions & 0 deletions oss/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ const (
HttpHeaderOssDate = "X-Oss-Date"
HttpHeaderOssContentSha256 = "X-Oss-Content-Sha256"
HttpHeaderOssNotification = "X-Oss-Notification"
HTTPHeaderOssEc = "X-Oss-Ec"
HTTPHeaderOssErr = "X-Oss-Err"
)

// HTTP Param
Expand Down
14 changes: 9 additions & 5 deletions oss/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@ type ServiceError struct {
RequestID string `xml:"RequestId"` // The UUID used to uniquely identify the request
HostID string `xml:"HostId"` // The OSS server cluster's Id
Endpoint string `xml:"Endpoint"`
Ec string `xml:"EC"`
RawMessage string // The raw messages from OSS
StatusCode int // HTTP status code

}

// Error implements interface error
func (e ServiceError) Error() string {
if e.Endpoint == "" {
return fmt.Sprintf("oss: service returned error: StatusCode=%d, ErrorCode=%s, ErrorMessage=\"%s\", RequestId=%s",
e.StatusCode, e.Code, e.Message, e.RequestID)
errorStr := fmt.Sprintf("oss: service returned error: StatusCode=%d, ErrorCode=%s, ErrorMessage=\"%s\", RequestId=%s", e.StatusCode, e.Code, e.Message, e.RequestID)
if len(e.Endpoint) > 0 {
errorStr = fmt.Sprintf("%s, Endpoint=%s", errorStr, e.Endpoint)
}
if len(e.Ec) > 0 {
errorStr = fmt.Sprintf("%s, Ec=%s", errorStr, e.Ec)
}
return fmt.Sprintf("oss: service returned error: StatusCode=%d, ErrorCode=%s, ErrorMessage=\"%s\", RequestId=%s, Endpoint=%s",
e.StatusCode, e.Code, e.Message, e.RequestID, e.Endpoint)
return errorStr
}

// UnexpectedStatusCodeError is returned when a storage service responds with neither an error
Expand Down

0 comments on commit 64b34dc

Please sign in to comment.