request.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  // request.go - the custom HTTP request for BCE
  16  
  17  package http
  18  
  19  import (
  20  	"context"
  21  	"fmt"
  22  	"io"
  23  	"net/http"
  24  	"strconv"
  25  	"strings"
  26  
  27  	"github.com/baidubce/bce-sdk-go/util"
  28  )
  29  
  30  // Reauest stands for the general http request structure to make request to the BCE services.
  31  type Request struct {
  32  	protocol string
  33  	host     string
  34  	port     int
  35  	method   string
  36  	uri      string
  37  	proxyUrl string
  38  	timeout  int
  39  	headers  map[string]string
  40  	params   map[string]string
  41  
  42  	// Optional body and length fields to set the body stream and content length
  43  	body       io.ReadCloser
  44  	length     int64
  45  	ctx        context.Context
  46  	httpClient *http.Client
  47  }
  48  
  49  func (r *Request) HTTPClient() *http.Client {
  50  	return r.httpClient
  51  }
  52  
  53  func (r *Request) SetHTTPClient(client *http.Client) {
  54  	if client != nil {
  55  		r.httpClient = client
  56  	}
  57  }
  58  
  59  func (r *Request) Context() context.Context {
  60  	return r.ctx
  61  }
  62  
  63  func (r *Request) SetContext(ctx context.Context) {
  64  	if ctx != nil {
  65  		r.ctx = ctx
  66  	}
  67  }
  68  
  69  func (r *Request) Protocol() string {
  70  	return r.protocol
  71  }
  72  
  73  func (r *Request) SetProtocol(protocol string) {
  74  	r.protocol = protocol
  75  }
  76  
  77  func (r *Request) Endpoint() string {
  78  	if r.host == "" {
  79  		return ""
  80  	}
  81  	return r.protocol + "://" + r.host
  82  }
  83  
  84  func (r *Request) SetEndpoint(endpoint string) {
  85  	pos := strings.Index(endpoint, "://")
  86  	rest := endpoint
  87  	if pos != -1 {
  88  		r.protocol = endpoint[0:pos]
  89  		rest = endpoint[pos+3:]
  90  	} else {
  91  		r.protocol = "http"
  92  	}
  93  
  94  	r.SetHost(rest)
  95  }
  96  
  97  func (r *Request) Host() string {
  98  	return r.host
  99  }
 100  
 101  func (r *Request) SetHost(host string) {
 102  	r.host = host
 103  	pos := strings.Index(host, ":")
 104  	if pos != -1 {
 105  		p, e := strconv.Atoi(host[pos+1:])
 106  		if e == nil {
 107  			r.port = p
 108  		}
 109  	}
 110  
 111  	if r.port == 0 {
 112  		if r.protocol == "http" {
 113  			r.port = 80
 114  		} else if r.protocol == "https" {
 115  			r.port = 443
 116  		}
 117  	}
 118  }
 119  
 120  func (r *Request) Port() int {
 121  	return r.port
 122  }
 123  
 124  func (r *Request) SetPort(port int) {
 125  	// Port can be set by the endpoint or host, this method is rarely used.
 126  	r.port = port
 127  }
 128  
 129  func (r *Request) Headers() map[string]string {
 130  	return r.headers
 131  }
 132  
 133  func (r *Request) SetHeaders(headers map[string]string) {
 134  	r.headers = headers
 135  }
 136  
 137  func (r *Request) Header(key string) string {
 138  	if v, ok := r.headers[key]; ok {
 139  		return v
 140  	}
 141  	return ""
 142  }
 143  
 144  func (r *Request) SetHeader(key, value string) {
 145  	if r.headers == nil {
 146  		r.headers = make(map[string]string)
 147  	}
 148  	r.headers[key] = value
 149  }
 150  
 151  func (r *Request) Params() map[string]string {
 152  	return r.params
 153  }
 154  
 155  func (r *Request) SetParams(params map[string]string) {
 156  	r.params = params
 157  }
 158  
 159  func (r *Request) Param(key string) string {
 160  	if v, ok := r.params[key]; ok {
 161  		return v
 162  	}
 163  	return ""
 164  }
 165  
 166  func (r *Request) SetParam(key, value string) {
 167  	if r.params == nil {
 168  		r.params = make(map[string]string)
 169  	}
 170  	r.params[key] = value
 171  }
 172  
 173  func (r *Request) QueryString() string {
 174  	buf := make([]string, 0, len(r.params))
 175  	for k, v := range r.params {
 176  		if len(v) == 0 {
 177  			buf = append(buf, util.UriEncode(k, true))
 178  		} else {
 179  			buf = append(buf, util.UriEncode(k, true)+"="+util.UriEncode(v, true))
 180  		}
 181  	}
 182  	return strings.Join(buf, "&")
 183  }
 184  
 185  func (r *Request) Method() string {
 186  	return r.method
 187  }
 188  
 189  func (r *Request) SetMethod(method string) {
 190  	r.method = method
 191  }
 192  
 193  func (r *Request) Uri() string {
 194  	return r.uri
 195  }
 196  
 197  func (r *Request) SetUri(uri string) {
 198  	r.uri = uri
 199  }
 200  
 201  func (r *Request) ProxyUrl() string {
 202  	return r.proxyUrl
 203  }
 204  
 205  func (r *Request) SetProxyUrl(url string) {
 206  	r.proxyUrl = url
 207  }
 208  
 209  func (r *Request) Timeout() int {
 210  	return r.timeout
 211  }
 212  
 213  func (r *Request) SetTimeout(timeout int) {
 214  	r.timeout = timeout
 215  }
 216  
 217  func (r *Request) Body() io.ReadCloser {
 218  	return r.body
 219  }
 220  
 221  func (r *Request) SetBody(stream io.ReadCloser) {
 222  	r.body = stream
 223  }
 224  
 225  func (r *Request) Length() int64 {
 226  	return r.length
 227  }
 228  
 229  func (r *Request) SetLength(l int64) {
 230  	r.length = l
 231  }
 232  
 233  func (r *Request) GenerateUrl(addPort bool) string {
 234  	if addPort {
 235  		return fmt.Sprintf("%s://%s:%d%s?%s",
 236  			r.protocol, r.host, r.port, r.uri, r.QueryString())
 237  	} else {
 238  		return fmt.Sprintf("%s://%s%s?%s", r.protocol, r.host, r.uri, r.QueryString())
 239  	}
 240  }
 241  
 242  func (r *Request) String() string {
 243  	header := make([]string, 0, len(r.headers))
 244  	for k, v := range r.headers {
 245  		header = append(header, "\t"+k+"="+v)
 246  	}
 247  	return fmt.Sprintf("\t%s %s\n%v",
 248  		r.method, r.GenerateUrl(false), strings.Join(header, "\n"))
 249  }
 250