acs_request.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*
  2. * Licensed under the Apache License, Version 2.0 (the "License");
  3. * you may not use this file except in compliance with the License.
  4. * You may obtain a copy of the License at
  5. *
  6. * http://www.apache.org/licenses/LICENSE-2.0
  7. *
  8. * Unless required by applicable law or agreed to in writing, software
  9. * distributed under the License is distributed on an "AS IS" BASIS,
  10. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. * See the License for the specific language governing permissions and
  12. * limitations under the License.
  13. */
  14. package requests
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "io"
  19. "reflect"
  20. "strconv"
  21. "strings"
  22. "time"
  23. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
  24. )
  25. const (
  26. RPC = "RPC"
  27. ROA = "ROA"
  28. HTTP = "HTTP"
  29. HTTPS = "HTTPS"
  30. DefaultHttpPort = "80"
  31. GET = "GET"
  32. PUT = "PUT"
  33. POST = "POST"
  34. DELETE = "DELETE"
  35. HEAD = "HEAD"
  36. OPTIONS = "OPTIONS"
  37. Json = "application/json"
  38. Xml = "application/xml"
  39. Raw = "application/octet-stream"
  40. Form = "application/x-www-form-urlencoded"
  41. Header = "Header"
  42. Query = "Query"
  43. Body = "Body"
  44. Path = "Path"
  45. HeaderSeparator = "\n"
  46. )
  47. // interface
  48. type AcsRequest interface {
  49. GetScheme() string
  50. GetMethod() string
  51. GetDomain() string
  52. GetPort() string
  53. GetRegionId() string
  54. GetHeaders() map[string]string
  55. GetQueryParams() map[string]string
  56. GetFormParams() map[string]string
  57. GetContent() []byte
  58. GetBodyReader() io.Reader
  59. GetStyle() string
  60. GetProduct() string
  61. GetVersion() string
  62. GetActionName() string
  63. GetAcceptFormat() string
  64. GetLocationServiceCode() string
  65. GetLocationEndpointType() string
  66. GetReadTimeout() time.Duration
  67. GetConnectTimeout() time.Duration
  68. SetReadTimeout(readTimeout time.Duration)
  69. SetConnectTimeout(connectTimeout time.Duration)
  70. SetHTTPSInsecure(isInsecure bool)
  71. GetHTTPSInsecure() *bool
  72. GetUserAgent() map[string]string
  73. SetStringToSign(stringToSign string)
  74. GetStringToSign() string
  75. SetDomain(domain string)
  76. SetContent(content []byte)
  77. SetScheme(scheme string)
  78. BuildUrl() string
  79. BuildQueries() string
  80. addHeaderParam(key, value string)
  81. addQueryParam(key, value string)
  82. addFormParam(key, value string)
  83. addPathParam(key, value string)
  84. }
  85. // base class
  86. type baseRequest struct {
  87. Scheme string
  88. Method string
  89. Domain string
  90. Port string
  91. RegionId string
  92. ReadTimeout time.Duration
  93. ConnectTimeout time.Duration
  94. isInsecure *bool
  95. userAgent map[string]string
  96. product string
  97. version string
  98. actionName string
  99. AcceptFormat string
  100. QueryParams map[string]string
  101. Headers map[string]string
  102. FormParams map[string]string
  103. Content []byte
  104. locationServiceCode string
  105. locationEndpointType string
  106. queries string
  107. stringToSign string
  108. }
  109. func (request *baseRequest) GetQueryParams() map[string]string {
  110. return request.QueryParams
  111. }
  112. func (request *baseRequest) GetFormParams() map[string]string {
  113. return request.FormParams
  114. }
  115. func (request *baseRequest) GetReadTimeout() time.Duration {
  116. return request.ReadTimeout
  117. }
  118. func (request *baseRequest) GetConnectTimeout() time.Duration {
  119. return request.ConnectTimeout
  120. }
  121. func (request *baseRequest) SetReadTimeout(readTimeout time.Duration) {
  122. request.ReadTimeout = readTimeout
  123. }
  124. func (request *baseRequest) SetConnectTimeout(connectTimeout time.Duration) {
  125. request.ConnectTimeout = connectTimeout
  126. }
  127. func (request *baseRequest) GetHTTPSInsecure() *bool {
  128. return request.isInsecure
  129. }
  130. func (request *baseRequest) SetHTTPSInsecure(isInsecure bool) {
  131. request.isInsecure = &isInsecure
  132. }
  133. func (request *baseRequest) GetContent() []byte {
  134. return request.Content
  135. }
  136. func (request *baseRequest) GetVersion() string {
  137. return request.version
  138. }
  139. func (request *baseRequest) GetActionName() string {
  140. return request.actionName
  141. }
  142. func (request *baseRequest) SetContent(content []byte) {
  143. request.Content = content
  144. }
  145. func (request *baseRequest) GetUserAgent() map[string]string {
  146. return request.userAgent
  147. }
  148. func (request *baseRequest) AppendUserAgent(key, value string) {
  149. newkey := true
  150. if request.userAgent == nil {
  151. request.userAgent = make(map[string]string)
  152. }
  153. if strings.ToLower(key) != "core" && strings.ToLower(key) != "go" {
  154. for tag, _ := range request.userAgent {
  155. if tag == key {
  156. request.userAgent[tag] = value
  157. newkey = false
  158. }
  159. }
  160. if newkey {
  161. request.userAgent[key] = value
  162. }
  163. }
  164. }
  165. func (request *baseRequest) addHeaderParam(key, value string) {
  166. request.Headers[key] = value
  167. }
  168. func (request *baseRequest) addQueryParam(key, value string) {
  169. request.QueryParams[key] = value
  170. }
  171. func (request *baseRequest) addFormParam(key, value string) {
  172. request.FormParams[key] = value
  173. }
  174. func (request *baseRequest) GetAcceptFormat() string {
  175. return request.AcceptFormat
  176. }
  177. func (request *baseRequest) GetLocationServiceCode() string {
  178. return request.locationServiceCode
  179. }
  180. func (request *baseRequest) GetLocationEndpointType() string {
  181. return request.locationEndpointType
  182. }
  183. func (request *baseRequest) GetProduct() string {
  184. return request.product
  185. }
  186. func (request *baseRequest) GetScheme() string {
  187. return request.Scheme
  188. }
  189. func (request *baseRequest) SetScheme(scheme string) {
  190. request.Scheme = scheme
  191. }
  192. func (request *baseRequest) GetMethod() string {
  193. return request.Method
  194. }
  195. func (request *baseRequest) GetDomain() string {
  196. return request.Domain
  197. }
  198. func (request *baseRequest) SetDomain(host string) {
  199. request.Domain = host
  200. }
  201. func (request *baseRequest) GetPort() string {
  202. return request.Port
  203. }
  204. func (request *baseRequest) GetRegionId() string {
  205. return request.RegionId
  206. }
  207. func (request *baseRequest) GetHeaders() map[string]string {
  208. return request.Headers
  209. }
  210. func (request *baseRequest) SetContentType(contentType string) {
  211. request.addHeaderParam("Content-Type", contentType)
  212. }
  213. func (request *baseRequest) GetContentType() (contentType string, contains bool) {
  214. contentType, contains = request.Headers["Content-Type"]
  215. return
  216. }
  217. func (request *baseRequest) SetStringToSign(stringToSign string) {
  218. request.stringToSign = stringToSign
  219. }
  220. func (request *baseRequest) GetStringToSign() string {
  221. return request.stringToSign
  222. }
  223. func defaultBaseRequest() (request *baseRequest) {
  224. request = &baseRequest{
  225. Scheme: "",
  226. AcceptFormat: "JSON",
  227. Method: GET,
  228. QueryParams: make(map[string]string),
  229. Headers: map[string]string{
  230. "x-sdk-client": "golang/1.0.0",
  231. "x-sdk-invoke-type": "normal",
  232. "Accept-Encoding": "identity",
  233. },
  234. FormParams: make(map[string]string),
  235. }
  236. return
  237. }
  238. func InitParams(request AcsRequest) (err error) {
  239. requestValue := reflect.ValueOf(request).Elem()
  240. err = flatRepeatedList(requestValue, request, "", "")
  241. return
  242. }
  243. func flatRepeatedList(dataValue reflect.Value, request AcsRequest, position, prefix string) (err error) {
  244. dataType := dataValue.Type()
  245. for i := 0; i < dataType.NumField(); i++ {
  246. field := dataType.Field(i)
  247. name, containsNameTag := field.Tag.Lookup("name")
  248. fieldPosition := position
  249. if fieldPosition == "" {
  250. fieldPosition, _ = field.Tag.Lookup("position")
  251. }
  252. typeTag, containsTypeTag := field.Tag.Lookup("type")
  253. if containsNameTag {
  254. if !containsTypeTag {
  255. // simple param
  256. key := prefix + name
  257. value := dataValue.Field(i).String()
  258. if dataValue.Field(i).Kind().String() == "map" {
  259. byt, _ := json.Marshal(dataValue.Field(i).Interface())
  260. value = string(byt)
  261. }
  262. err = addParam(request, fieldPosition, key, value)
  263. if err != nil {
  264. return
  265. }
  266. } else if typeTag == "Repeated" {
  267. // repeated param
  268. repeatedFieldValue := dataValue.Field(i)
  269. if repeatedFieldValue.Kind() != reflect.Slice {
  270. // possible value: {"[]string", "*[]struct"}, we must call Elem() in the last condition
  271. repeatedFieldValue = repeatedFieldValue.Elem()
  272. }
  273. if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
  274. for m := 0; m < repeatedFieldValue.Len(); m++ {
  275. elementValue := repeatedFieldValue.Index(m)
  276. key := prefix + name + "." + strconv.Itoa(m+1)
  277. if elementValue.Type().Kind().String() == "string" {
  278. value := elementValue.String()
  279. err = addParam(request, fieldPosition, key, value)
  280. if err != nil {
  281. return
  282. }
  283. } else {
  284. err = flatRepeatedList(elementValue, request, fieldPosition, key+".")
  285. if err != nil {
  286. return
  287. }
  288. }
  289. }
  290. }
  291. }
  292. }
  293. }
  294. return
  295. }
  296. func addParam(request AcsRequest, position, name, value string) (err error) {
  297. if len(value) > 0 {
  298. switch position {
  299. case Header:
  300. request.addHeaderParam(name, value)
  301. case Query:
  302. request.addQueryParam(name, value)
  303. case Path:
  304. request.addPathParam(name, value)
  305. case Body:
  306. request.addFormParam(name, value)
  307. default:
  308. errMsg := fmt.Sprintf(errors.UnsupportedParamPositionErrorMessage, position)
  309. err = errors.NewClientError(errors.UnsupportedParamPositionErrorCode, errMsg, nil)
  310. }
  311. }
  312. return
  313. }