builder.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  // builder.go - defines the RequestBuilder structure for BCE servies
  16  
  17  package bce
  18  
  19  import (
  20  	"encoding/json"
  21  	"fmt"
  22  )
  23  
  24  // RequestBuilder holds config data for bce request.
  25  // Some of fields are required and the others are optional.
  26  // The builder pattern can simplify the execution of requests.
  27  type RequestBuilder struct {
  28  	client Client
  29  
  30  	url         string            // required
  31  	method      string            // required
  32  	queryParams map[string]string // optional
  33  	headers     map[string]string // optional
  34  	body        interface{}       // optional
  35  	result      interface{}       // optional
  36  }
  37  
  38  // create RequestBuilder with the client.
  39  func NewRequestBuilder(client Client) *RequestBuilder {
  40  	return &RequestBuilder{
  41  		client: client,
  42  	}
  43  }
  44  
  45  func (b *RequestBuilder) WithURL(url string) *RequestBuilder {
  46  	b.url = url
  47  	return b
  48  }
  49  
  50  func (b *RequestBuilder) WithMethod(method string) *RequestBuilder {
  51  	b.method = method
  52  	return b
  53  }
  54  
  55  // set query param with the key/value directly.
  56  func (b *RequestBuilder) WithQueryParam(key, value string) *RequestBuilder {
  57  	if b.queryParams == nil {
  58  		b.queryParams = make(map[string]string)
  59  	}
  60  	b.queryParams[key] = value
  61  	return b
  62  }
  63  
  64  // set query param with the key/value only when the value is not blank.
  65  func (b *RequestBuilder) WithQueryParamFilter(key, value string) *RequestBuilder {
  66  	if len(value) == 0 {
  67  		return b
  68  	}
  69  	return b.WithQueryParam(key, value)
  70  }
  71  
  72  func (b *RequestBuilder) WithQueryParams(params map[string]string) *RequestBuilder {
  73  	if b.queryParams == nil {
  74  		b.queryParams = params
  75  	} else {
  76  		for key, value := range params {
  77  			b.queryParams[key] = value
  78  		}
  79  	}
  80  	return b
  81  }
  82  
  83  func (b *RequestBuilder) WithHeader(key, value string) *RequestBuilder {
  84  	if b.headers == nil {
  85  		b.headers = make(map[string]string)
  86  	}
  87  	b.headers[key] = value
  88  	return b
  89  }
  90  
  91  func (b *RequestBuilder) WithHeaders(headers map[string]string) *RequestBuilder {
  92  	if b.headers == nil {
  93  		b.headers = headers
  94  	} else {
  95  		for key, value := range headers {
  96  			b.headers[key] = value
  97  		}
  98  	}
  99  	return b
 100  }
 101  
 102  func (b *RequestBuilder) WithBody(body interface{}) *RequestBuilder {
 103  	b.body = body
 104  	return b
 105  }
 106  
 107  func (b *RequestBuilder) WithResult(result interface{}) *RequestBuilder {
 108  	b.result = result
 109  	return b
 110  }
 111  
 112  // Do will send request to bce and get result with the builder's parameters.
 113  func (b *RequestBuilder) Do() error {
 114  	if err := b.validate(); err != nil {
 115  		return err
 116  	}
 117  
 118  	// build BceRequest
 119  	req, err := b.buildBceRequest()
 120  	if err != nil {
 121  		return err
 122  	}
 123  
 124  	// get result from BceResponse
 125  	if err := b.buildBceResponse(req); err != nil {
 126  		return err
 127  	}
 128  
 129  	return nil
 130  }
 131  
 132  // Validate if the required fields are providered.
 133  func (b *RequestBuilder) validate() error {
 134  	if len(b.url) == 0 {
 135  		return fmt.Errorf("The url can't be null.")
 136  	}
 137  	if len(b.method) == 0 {
 138  		return fmt.Errorf("The method can't be null.")
 139  	}
 140  	if b.client == nil {
 141  		return fmt.Errorf("The client can't be null.")
 142  	}
 143  	return nil
 144  }
 145  
 146  func (b *RequestBuilder) buildBceRequest() (*BceRequest, error) {
 147  	// Build the request
 148  	req := &BceRequest{}
 149  	req.SetUri(b.url)
 150  	req.SetMethod(b.method)
 151  
 152  	if b.headers != nil {
 153  		req.SetHeaders(b.headers)
 154  	}
 155  	if b.queryParams != nil {
 156  		req.SetParams(b.queryParams)
 157  	}
 158  	if b.body != nil {
 159  		bodyBytes, err := json.Marshal(b.body)
 160  		if err != nil {
 161  			return nil, err
 162  		}
 163  		body, err := NewBodyFromBytes(bodyBytes)
 164  		if err != nil {
 165  			return nil, err
 166  		}
 167  		req.SetBody(body)
 168  	}
 169  
 170  	return req, nil
 171  }
 172  
 173  func (b *RequestBuilder) buildBceResponse(req *BceRequest) error {
 174  	// Send request and get response
 175  	resp := &BceResponse{}
 176  	if err := b.client.SendRequest(req, resp); err != nil {
 177  		return err
 178  	}
 179  	if resp.IsFail() {
 180  		return resp.ServiceError()
 181  	}
 182  	defer resp.Body().Close()
 183  
 184  	if b.result == nil {
 185  		return nil
 186  	}
 187  
 188  	return resp.ParseJsonBody(b.result)
 189  }
 190