-
Notifications
You must be signed in to change notification settings - Fork 41
/
unpacker.go
123 lines (104 loc) · 3.28 KB
/
unpacker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// +-------------------------------------------------------------------------
// | 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 request
import (
"bytes"
"fmt"
"net/http"
"reflect"
"strings"
"github.com/yunify/qingcloud-sdk-go/logger"
"github.com/yunify/qingcloud-sdk-go/request/data"
"github.com/yunify/qingcloud-sdk-go/request/errors"
"github.com/yunify/qingcloud-sdk-go/utils"
)
// Unpacker is the response unpacker.
type Unpacker struct {
operation *data.Operation
httpResponse *http.Response
output *reflect.Value
}
// UnpackHTTPRequest unpack the http response with an operation, http response and an output.
func (u *Unpacker) UnpackHTTPRequest(o *data.Operation, r *http.Response, x *reflect.Value) error {
u.operation = o
u.httpResponse = r
u.output = x
err := u.parseResponse()
if err != nil {
return err
}
err = u.parseError()
if err != nil {
return err
}
return nil
}
func (u *Unpacker) parseResponse() error {
if u.httpResponse.StatusCode == 200 {
var resp = u.httpResponse
if resp == nil {
return fmt.Errorf("http response is nil point")
}
var contentType = resp.Header.Get("Content-Type")
if strings.HasPrefix(contentType, "application/json") {
buffer := &bytes.Buffer{}
buffer.ReadFrom(u.httpResponse.Body)
u.httpResponse.Body.Close()
logger.Info(fmt.Sprintf(
"Response json string: [%d] %s",
utils.StringToUnixInt(u.httpResponse.Header.Get("Date"), "RFC 822"),
string(buffer.Bytes())))
_, err := utils.JSONDecode(buffer.Bytes(), u.output.Interface())
if err != nil {
return err
}
if !u.output.IsValid() {
return fmt.Errorf("API Gateway output format error")
}
}
} else {
u.httpResponse.Body.Close()
err := fmt.Errorf("Response StatusCode: %d", u.httpResponse.StatusCode)
logger.Error(err.Error())
return err
}
return nil
}
func (u *Unpacker) parseError() error {
if u.output.IsNil() {
return fmt.Errorf("nil returned")
}
retCodeValue := u.output.Elem().FieldByName("RetCode")
messageValue := u.output.Elem().FieldByName("Message")
if retCodeValue.IsValid() && retCodeValue.Type().String() == "*int" &&
retCodeValue.Elem().IsValid() {
if retCodeValue.Elem().Int() == 0 {
return nil
}
err := &errors.QingCloudError{
RetCode: int(retCodeValue.Elem().Int()),
}
if messageValue.IsValid() && messageValue.Type().String() == "*string" {
if messageValue.Elem().IsValid() {
err.Message = messageValue.Elem().String()
} else {
err.Message = "null"
}
}
return err
}
return fmt.Errorf("invalid retCodeValue %v returned", retCodeValue)
}