acs_request.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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. SetVersion(version string)
  63. GetActionName() string
  64. GetAcceptFormat() string
  65. GetLocationServiceCode() string
  66. GetLocationEndpointType() string
  67. GetReadTimeout() time.Duration
  68. GetConnectTimeout() time.Duration
  69. SetReadTimeout(readTimeout time.Duration)
  70. SetConnectTimeout(connectTimeout time.Duration)
  71. SetHTTPSInsecure(isInsecure bool)
  72. GetHTTPSInsecure() *bool
  73. GetUserAgent() map[string]string
  74. SetStringToSign(stringToSign string)
  75. GetStringToSign() string
  76. SetDomain(domain string)
  77. SetContent(content []byte)
  78. SetScheme(scheme string)
  79. BuildUrl() string
  80. BuildQueries() string
  81. addHeaderParam(key, value string)
  82. addQueryParam(key, value string)
  83. addFormParam(key, value string)
  84. addPathParam(key, value string)
  85. }
  86. // base class
  87. type baseRequest struct {
  88. Scheme string
  89. Method string
  90. Domain string
  91. Port string
  92. RegionId string
  93. ReadTimeout time.Duration
  94. ConnectTimeout time.Duration
  95. isInsecure *bool
  96. userAgent map[string]string
  97. product string
  98. version string
  99. actionName string
  100. AcceptFormat string
  101. QueryParams map[string]string
  102. Headers map[string]string
  103. FormParams map[string]string
  104. Content []byte
  105. locationServiceCode string
  106. locationEndpointType string
  107. queries string
  108. stringToSign string
  109. }
  110. func (request *baseRequest) GetQueryParams() map[string]string {
  111. return request.QueryParams
  112. }
  113. func (request *baseRequest) GetFormParams() map[string]string {
  114. return request.FormParams
  115. }
  116. func (request *baseRequest) GetReadTimeout() time.Duration {
  117. return request.ReadTimeout
  118. }
  119. func (request *baseRequest) GetConnectTimeout() time.Duration {
  120. return request.ConnectTimeout
  121. }
  122. func (request *baseRequest) SetReadTimeout(readTimeout time.Duration) {
  123. request.ReadTimeout = readTimeout
  124. }
  125. func (request *baseRequest) SetConnectTimeout(connectTimeout time.Duration) {
  126. request.ConnectTimeout = connectTimeout
  127. }
  128. func (request *baseRequest) GetHTTPSInsecure() *bool {
  129. return request.isInsecure
  130. }
  131. func (request *baseRequest) SetHTTPSInsecure(isInsecure bool) {
  132. request.isInsecure = &isInsecure
  133. }
  134. func (request *baseRequest) GetContent() []byte {
  135. return request.Content
  136. }
  137. func (request *baseRequest) SetVersion(version string) {
  138. request.version = version
  139. }
  140. func (request *baseRequest) GetVersion() string {
  141. return request.version
  142. }
  143. func (request *baseRequest) GetActionName() string {
  144. return request.actionName
  145. }
  146. func (request *baseRequest) SetContent(content []byte) {
  147. request.Content = content
  148. }
  149. func (request *baseRequest) GetUserAgent() map[string]string {
  150. return request.userAgent
  151. }
  152. func (request *baseRequest) AppendUserAgent(key, value string) {
  153. newkey := true
  154. if request.userAgent == nil {
  155. request.userAgent = make(map[string]string)
  156. }
  157. if strings.ToLower(key) != "core" && strings.ToLower(key) != "go" {
  158. for tag, _ := range request.userAgent {
  159. if tag == key {
  160. request.userAgent[tag] = value
  161. newkey = false
  162. }
  163. }
  164. if newkey {
  165. request.userAgent[key] = value
  166. }
  167. }
  168. }
  169. func (request *baseRequest) addHeaderParam(key, value string) {
  170. request.Headers[key] = value
  171. }
  172. func (request *baseRequest) addQueryParam(key, value string) {
  173. request.QueryParams[key] = value
  174. }
  175. func (request *baseRequest) addFormParam(key, value string) {
  176. request.FormParams[key] = value
  177. }
  178. func (request *baseRequest) GetAcceptFormat() string {
  179. return request.AcceptFormat
  180. }
  181. func (request *baseRequest) GetLocationServiceCode() string {
  182. return request.locationServiceCode
  183. }
  184. func (request *baseRequest) GetLocationEndpointType() string {
  185. return request.locationEndpointType
  186. }
  187. func (request *baseRequest) GetProduct() string {
  188. return request.product
  189. }
  190. func (request *baseRequest) GetScheme() string {
  191. return request.Scheme
  192. }
  193. func (request *baseRequest) SetScheme(scheme string) {
  194. request.Scheme = scheme
  195. }
  196. func (request *baseRequest) GetMethod() string {
  197. return request.Method
  198. }
  199. func (request *baseRequest) GetDomain() string {
  200. return request.Domain
  201. }
  202. func (request *baseRequest) SetDomain(host string) {
  203. request.Domain = host
  204. }
  205. func (request *baseRequest) GetPort() string {
  206. return request.Port
  207. }
  208. func (request *baseRequest) GetRegionId() string {
  209. return request.RegionId
  210. }
  211. func (request *baseRequest) GetHeaders() map[string]string {
  212. return request.Headers
  213. }
  214. func (request *baseRequest) SetContentType(contentType string) {
  215. request.addHeaderParam("Content-Type", contentType)
  216. }
  217. func (request *baseRequest) GetContentType() (contentType string, contains bool) {
  218. contentType, contains = request.Headers["Content-Type"]
  219. return
  220. }
  221. func (request *baseRequest) SetStringToSign(stringToSign string) {
  222. request.stringToSign = stringToSign
  223. }
  224. func (request *baseRequest) GetStringToSign() string {
  225. return request.stringToSign
  226. }
  227. func defaultBaseRequest() (request *baseRequest) {
  228. request = &baseRequest{
  229. Scheme: "",
  230. AcceptFormat: "JSON",
  231. Method: GET,
  232. QueryParams: make(map[string]string),
  233. Headers: map[string]string{
  234. "x-sdk-client": "golang/1.0.0",
  235. "x-sdk-invoke-type": "normal",
  236. "Accept-Encoding": "identity",
  237. },
  238. FormParams: make(map[string]string),
  239. }
  240. return
  241. }
  242. func InitParams(request AcsRequest) (err error) {
  243. requestValue := reflect.ValueOf(request).Elem()
  244. err = flatRepeatedList(requestValue, request, "", "")
  245. return
  246. }
  247. func flatRepeatedList(dataValue reflect.Value, request AcsRequest, position, prefix string) (err error) {
  248. dataType := dataValue.Type()
  249. for i := 0; i < dataType.NumField(); i++ {
  250. field := dataType.Field(i)
  251. name, containsNameTag := field.Tag.Lookup("name")
  252. fieldPosition := position
  253. if fieldPosition == "" {
  254. fieldPosition, _ = field.Tag.Lookup("position")
  255. }
  256. typeTag, containsTypeTag := field.Tag.Lookup("type")
  257. if containsNameTag {
  258. if !containsTypeTag {
  259. // simple param
  260. key := prefix + name
  261. value := dataValue.Field(i).String()
  262. if dataValue.Field(i).Kind().String() == "map" {
  263. byt, _ := json.Marshal(dataValue.Field(i).Interface())
  264. value = string(byt)
  265. if value == "null" {
  266. value = ""
  267. }
  268. }
  269. err = addParam(request, fieldPosition, key, value)
  270. if err != nil {
  271. return
  272. }
  273. } else if typeTag == "Repeated" {
  274. // repeated param
  275. err = handleRepeatedParams(request, dataValue, prefix, name, fieldPosition, i)
  276. if err != nil {
  277. return
  278. }
  279. } else if typeTag == "Struct" {
  280. err = handleStruct(request, dataValue, prefix, name, fieldPosition, i)
  281. if err != nil {
  282. return
  283. }
  284. }
  285. }
  286. }
  287. return
  288. }
  289. func handleRepeatedParams(request AcsRequest, dataValue reflect.Value, prefix, name, fieldPosition string, index int) (err error) {
  290. repeatedFieldValue := dataValue.Field(index)
  291. if repeatedFieldValue.Kind() != reflect.Slice {
  292. // possible value: {"[]string", "*[]struct"}, we must call Elem() in the last condition
  293. repeatedFieldValue = repeatedFieldValue.Elem()
  294. }
  295. if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
  296. for m := 0; m < repeatedFieldValue.Len(); m++ {
  297. elementValue := repeatedFieldValue.Index(m)
  298. key := prefix + name + "." + strconv.Itoa(m+1)
  299. if elementValue.Type().Kind().String() == "string" {
  300. value := elementValue.String()
  301. err = addParam(request, fieldPosition, key, value)
  302. if err != nil {
  303. return
  304. }
  305. } else {
  306. err = flatRepeatedList(elementValue, request, fieldPosition, key+".")
  307. if err != nil {
  308. return
  309. }
  310. }
  311. }
  312. }
  313. return nil
  314. }
  315. func handleStruct(request AcsRequest, dataValue reflect.Value, prefix, name, fieldPosition string, index int) (err error) {
  316. valueField := dataValue.Field(index)
  317. if valueField.IsValid() && valueField.String() != "" {
  318. valueFieldType := valueField.Type()
  319. for m := 0; m < valueFieldType.NumField(); m++ {
  320. fieldName := valueFieldType.Field(m).Name
  321. elementValue := valueField.FieldByName(fieldName)
  322. key := prefix + name + "." + fieldName
  323. if elementValue.Type().String() == "[]string" {
  324. if elementValue.IsNil() {
  325. continue
  326. }
  327. for j := 0; j < elementValue.Len(); j++ {
  328. err = addParam(request, fieldPosition, key+"."+strconv.Itoa(j+1), elementValue.Index(j).String())
  329. if err != nil {
  330. return
  331. }
  332. }
  333. } else {
  334. if elementValue.Type().Kind().String() == "string" {
  335. value := elementValue.String()
  336. err = addParam(request, fieldPosition, key, value)
  337. if err != nil {
  338. return
  339. }
  340. } else if elementValue.Type().Kind().String() == "struct" {
  341. err = flatRepeatedList(elementValue, request, fieldPosition, key+".")
  342. if err != nil {
  343. return
  344. }
  345. } else if !elementValue.IsNil() {
  346. repeatedFieldValue := elementValue.Elem()
  347. if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
  348. for m := 0; m < repeatedFieldValue.Len(); m++ {
  349. elementValue := repeatedFieldValue.Index(m)
  350. err = flatRepeatedList(elementValue, request, fieldPosition, key+"."+strconv.Itoa(m+1)+".")
  351. if err != nil {
  352. return
  353. }
  354. }
  355. }
  356. }
  357. }
  358. }
  359. }
  360. return nil
  361. }
  362. func addParam(request AcsRequest, position, name, value string) (err error) {
  363. if len(value) > 0 {
  364. switch position {
  365. case Header:
  366. request.addHeaderParam(name, value)
  367. case Query:
  368. request.addQueryParam(name, value)
  369. case Path:
  370. request.addPathParam(name, value)
  371. case Body:
  372. request.addFormParam(name, value)
  373. default:
  374. errMsg := fmt.Sprintf(errors.UnsupportedParamPositionErrorMessage, position)
  375. err = errors.NewClientError(errors.UnsupportedParamPositionErrorCode, errMsg, nil)
  376. }
  377. }
  378. return
  379. }