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