acs_request.go 8.3 KB

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