acs_request.go 7.6 KB

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