response.go raw
1 /*
2 * Copyright 2017 Baidu, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11 * either express or implied. See the License for the specific language governing permissions
12 * and limitations under the License.
13 */
14
15 // response.go - defines the common BCE services response
16
17 package bce
18
19 import (
20 "bytes"
21 "encoding/json"
22 "io"
23 "io/ioutil"
24 "strings"
25 "time"
26
27 "github.com/baidubce/bce-sdk-go/http"
28 )
29
30 // BceResponse defines the response structure for receiving BCE services response.
31 type BceResponse struct {
32 statusCode int
33 statusText string
34 requestId string
35 debugId string
36 response *http.Response
37 serviceError *BceServiceError
38 }
39
40 func (r *BceResponse) IsFail() bool {
41 return r.response.StatusCode() >= 400
42 }
43
44 func (r *BceResponse) StatusCode() int {
45 return r.statusCode
46 }
47
48 func (r *BceResponse) StatusText() string {
49 return r.statusText
50 }
51
52 func (r *BceResponse) RequestId() string {
53 return r.requestId
54 }
55
56 func (r *BceResponse) DebugId() string {
57 return r.debugId
58 }
59
60 func (r *BceResponse) Header(key string) string {
61 return r.response.GetHeader(key)
62 }
63
64 func (r *BceResponse) Headers() map[string]string {
65 return r.response.GetHeaders()
66 }
67
68 func (r *BceResponse) Body() io.ReadCloser {
69 return r.response.Body()
70 }
71
72 func (r *BceResponse) SetHttpResponse(response *http.Response) {
73 r.response = response
74 }
75
76 func (r *BceResponse) ElapsedTime() time.Duration {
77 return r.response.ElapsedTime()
78 }
79
80 func (r *BceResponse) ServiceError() *BceServiceError {
81 return r.serviceError
82 }
83
84 func (r *BceResponse) ParseResponse() {
85 r.statusCode = r.response.StatusCode()
86 r.statusText = r.response.StatusText()
87 r.requestId = r.response.GetHeader(http.BCE_REQUEST_ID)
88 r.debugId = r.response.GetHeader(http.BCE_DEBUG_ID)
89 if r.IsFail() {
90 r.serviceError = NewBceServiceError("", r.statusText, r.requestId, r.statusCode)
91
92 // First try to read the error `Code' and `Message' from body
93 rawBody, _ := ioutil.ReadAll(r.Body())
94 defer r.Body().Close()
95 if len(rawBody) != 0 {
96 jsonDecoder := json.NewDecoder(bytes.NewBuffer(rawBody))
97 if err := jsonDecoder.Decode(r.serviceError); err != nil {
98 r.serviceError = NewBceServiceError(
99 EMALFORMED_JSON,
100 "Service json error message decode failed",
101 r.requestId,
102 r.statusCode)
103 }
104 return
105 }
106
107 // Then guess the `Message' from by the return status code
108 switch r.statusCode {
109 case 400:
110 r.serviceError.Code = EINVALID_HTTP_REQUEST
111 case 403:
112 r.serviceError.Code = EACCESS_DENIED
113 case 412:
114 r.serviceError.Code = EPRECONDITION_FAILED
115 case 500:
116 r.serviceError.Code = EINTERNAL_ERROR
117 default:
118 words := strings.Split(r.statusText, " ")
119 r.serviceError.Code = strings.Join(words[1:], "")
120 }
121 }
122 }
123
124 func (r *BceResponse) ParseJsonBody(result interface{}) error {
125 defer r.Body().Close()
126 jsonDecoder := json.NewDecoder(r.Body())
127 return jsonDecoder.Decode(result)
128 }
129