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