rclone/vendor/github.com/yunify/qingstor-sdk-go/v3/request/unpacker/qingstor.go

103 lines
3.0 KiB
Go

// +-------------------------------------------------------------------------
// | Copyright (C) 2016 Yunify, Inc.
// +-------------------------------------------------------------------------
// | Licensed under the Apache License, Version 2.0 (the "License");
// | you may not use this work except in compliance with the License.
// | You may obtain a copy of the License in the LICENSE file, or 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 unpacker
import (
"bytes"
"encoding/json"
"io"
"net/http"
"reflect"
"github.com/yunify/qingstor-sdk-go/v3/logger"
"github.com/yunify/qingstor-sdk-go/v3/request/data"
"github.com/yunify/qingstor-sdk-go/v3/request/errors"
)
// QingStorUnpacker is the response unpacker for QingStor service.
type QingStorUnpacker struct {
baseUnpacker *BaseUnpacker
}
// UnpackHTTPRequest unpack the http response with an operation, http response and an output.
func (qu *QingStorUnpacker) UnpackHTTPRequest(o *data.Operation, r *http.Response, x *reflect.Value) error {
qu.baseUnpacker = &BaseUnpacker{}
err := qu.baseUnpacker.UnpackHTTPRequest(o, r, x)
if err != nil {
return err
}
err = qu.parseError()
if err != nil {
return err
}
// Close body for every API except GetObject and ImageProcess.
if o.APIName != "GET Object" && o.APIName != "Image Process" && r.Body != nil {
err = r.Body.Close()
if err != nil {
return err
}
r.Body = nil
}
return nil
}
func (qu *QingStorUnpacker) parseError() error {
if qu.baseUnpacker.isResponseRight() {
return nil
}
// QingStor nginx could refuse user's request directly and only return status code.
// We should handle this and build a qingstor error with message.
if qu.baseUnpacker.httpResponse.Header.Get("Content-Type") != "application/json" {
qsError := &errors.QingStorError{
StatusCode: qu.baseUnpacker.httpResponse.StatusCode,
Message: http.StatusText(qu.baseUnpacker.httpResponse.StatusCode),
}
return qsError
}
buffer := &bytes.Buffer{}
_, err := io.Copy(buffer, qu.baseUnpacker.httpResponse.Body)
if err != nil {
logger.Errorf(nil, "Copy from error response body failed for %v", err)
return err
}
err = qu.baseUnpacker.httpResponse.Body.Close()
if err != nil {
logger.Errorf(nil, "Close error response body failed for %v", err)
return err
}
qsError := &errors.QingStorError{}
if buffer.Len() > 0 {
err := json.Unmarshal(buffer.Bytes(), qsError)
if err != nil {
return err
}
}
qsError.StatusCode = qu.baseUnpacker.httpResponse.StatusCode
if qsError.RequestID == "" {
qsError.RequestID = qu.baseUnpacker.httpResponse.Header.Get(http.CanonicalHeaderKey("X-QS-Request-ID"))
}
return qsError
}