123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- /*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package requests
- import (
- "encoding/json"
- "fmt"
- "io"
- "reflect"
- "strconv"
- "strings"
- "time"
- "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
- )
- const (
- RPC = "RPC"
- ROA = "ROA"
- HTTP = "HTTP"
- HTTPS = "HTTPS"
- DefaultHttpPort = "80"
- GET = "GET"
- PUT = "PUT"
- POST = "POST"
- DELETE = "DELETE"
- HEAD = "HEAD"
- OPTIONS = "OPTIONS"
- Json = "application/json"
- Xml = "application/xml"
- Raw = "application/octet-stream"
- Form = "application/x-www-form-urlencoded"
- Header = "Header"
- Query = "Query"
- Body = "Body"
- Path = "Path"
- HeaderSeparator = "\n"
- )
- // interface
- type AcsRequest interface {
- GetScheme() string
- GetMethod() string
- GetDomain() string
- GetPort() string
- GetRegionId() string
- GetHeaders() map[string]string
- GetQueryParams() map[string]string
- GetFormParams() map[string]string
- GetContent() []byte
- GetBodyReader() io.Reader
- GetStyle() string
- GetProduct() string
- GetVersion() string
- SetVersion(version string)
- GetActionName() string
- GetAcceptFormat() string
- GetLocationServiceCode() string
- GetLocationEndpointType() string
- GetReadTimeout() time.Duration
- GetConnectTimeout() time.Duration
- SetReadTimeout(readTimeout time.Duration)
- SetConnectTimeout(connectTimeout time.Duration)
- SetHTTPSInsecure(isInsecure bool)
- GetHTTPSInsecure() *bool
- GetUserAgent() map[string]string
- SetStringToSign(stringToSign string)
- GetStringToSign() string
- SetDomain(domain string)
- SetContent(content []byte)
- SetScheme(scheme string)
- BuildUrl() string
- BuildQueries() string
- addHeaderParam(key, value string)
- addQueryParam(key, value string)
- addFormParam(key, value string)
- addPathParam(key, value string)
- }
- // base class
- type baseRequest struct {
- Scheme string
- Method string
- Domain string
- Port string
- RegionId string
- ReadTimeout time.Duration
- ConnectTimeout time.Duration
- isInsecure *bool
- userAgent map[string]string
- product string
- version string
- actionName string
- AcceptFormat string
- QueryParams map[string]string
- Headers map[string]string
- FormParams map[string]string
- Content []byte
- locationServiceCode string
- locationEndpointType string
- queries string
- stringToSign string
- }
- func (request *baseRequest) GetQueryParams() map[string]string {
- return request.QueryParams
- }
- func (request *baseRequest) GetFormParams() map[string]string {
- return request.FormParams
- }
- func (request *baseRequest) GetReadTimeout() time.Duration {
- return request.ReadTimeout
- }
- func (request *baseRequest) GetConnectTimeout() time.Duration {
- return request.ConnectTimeout
- }
- func (request *baseRequest) SetReadTimeout(readTimeout time.Duration) {
- request.ReadTimeout = readTimeout
- }
- func (request *baseRequest) SetConnectTimeout(connectTimeout time.Duration) {
- request.ConnectTimeout = connectTimeout
- }
- func (request *baseRequest) GetHTTPSInsecure() *bool {
- return request.isInsecure
- }
- func (request *baseRequest) SetHTTPSInsecure(isInsecure bool) {
- request.isInsecure = &isInsecure
- }
- func (request *baseRequest) GetContent() []byte {
- return request.Content
- }
- func (request *baseRequest) SetVersion(version string) {
- request.version = version
- }
- func (request *baseRequest) GetVersion() string {
- return request.version
- }
- func (request *baseRequest) GetActionName() string {
- return request.actionName
- }
- func (request *baseRequest) SetContent(content []byte) {
- request.Content = content
- }
- func (request *baseRequest) GetUserAgent() map[string]string {
- return request.userAgent
- }
- func (request *baseRequest) AppendUserAgent(key, value string) {
- newkey := true
- if request.userAgent == nil {
- request.userAgent = make(map[string]string)
- }
- if strings.ToLower(key) != "core" && strings.ToLower(key) != "go" {
- for tag, _ := range request.userAgent {
- if tag == key {
- request.userAgent[tag] = value
- newkey = false
- }
- }
- if newkey {
- request.userAgent[key] = value
- }
- }
- }
- func (request *baseRequest) addHeaderParam(key, value string) {
- request.Headers[key] = value
- }
- func (request *baseRequest) addQueryParam(key, value string) {
- request.QueryParams[key] = value
- }
- func (request *baseRequest) addFormParam(key, value string) {
- request.FormParams[key] = value
- }
- func (request *baseRequest) GetAcceptFormat() string {
- return request.AcceptFormat
- }
- func (request *baseRequest) GetLocationServiceCode() string {
- return request.locationServiceCode
- }
- func (request *baseRequest) GetLocationEndpointType() string {
- return request.locationEndpointType
- }
- func (request *baseRequest) GetProduct() string {
- return request.product
- }
- func (request *baseRequest) GetScheme() string {
- return request.Scheme
- }
- func (request *baseRequest) SetScheme(scheme string) {
- request.Scheme = scheme
- }
- func (request *baseRequest) GetMethod() string {
- return request.Method
- }
- func (request *baseRequest) GetDomain() string {
- return request.Domain
- }
- func (request *baseRequest) SetDomain(host string) {
- request.Domain = host
- }
- func (request *baseRequest) GetPort() string {
- return request.Port
- }
- func (request *baseRequest) GetRegionId() string {
- return request.RegionId
- }
- func (request *baseRequest) GetHeaders() map[string]string {
- return request.Headers
- }
- func (request *baseRequest) SetContentType(contentType string) {
- request.addHeaderParam("Content-Type", contentType)
- }
- func (request *baseRequest) GetContentType() (contentType string, contains bool) {
- contentType, contains = request.Headers["Content-Type"]
- return
- }
- func (request *baseRequest) SetStringToSign(stringToSign string) {
- request.stringToSign = stringToSign
- }
- func (request *baseRequest) GetStringToSign() string {
- return request.stringToSign
- }
- func defaultBaseRequest() (request *baseRequest) {
- request = &baseRequest{
- Scheme: "",
- AcceptFormat: "JSON",
- Method: GET,
- QueryParams: make(map[string]string),
- Headers: map[string]string{
- "x-sdk-client": "golang/1.0.0",
- "x-sdk-invoke-type": "normal",
- "Accept-Encoding": "identity",
- },
- FormParams: make(map[string]string),
- }
- return
- }
- func InitParams(request AcsRequest) (err error) {
- requestValue := reflect.ValueOf(request).Elem()
- err = flatRepeatedList(requestValue, request, "", "")
- return
- }
- func flatRepeatedList(dataValue reflect.Value, request AcsRequest, position, prefix string) (err error) {
- dataType := dataValue.Type()
- for i := 0; i < dataType.NumField(); i++ {
- field := dataType.Field(i)
- name, containsNameTag := field.Tag.Lookup("name")
- fieldPosition := position
- if fieldPosition == "" {
- fieldPosition, _ = field.Tag.Lookup("position")
- }
- typeTag, containsTypeTag := field.Tag.Lookup("type")
- if containsNameTag {
- if !containsTypeTag {
- // simple param
- key := prefix + name
- value := dataValue.Field(i).String()
- if dataValue.Field(i).Kind().String() == "map" {
- byt, _ := json.Marshal(dataValue.Field(i).Interface())
- value = string(byt)
- if value == "null" {
- value = ""
- }
- }
- err = addParam(request, fieldPosition, key, value)
- if err != nil {
- return
- }
- } else if typeTag == "Repeated" {
- // repeated param
- err = handleRepeatedParams(request, dataValue, prefix, name, fieldPosition, i)
- if err != nil {
- return
- }
- } else if typeTag == "Struct" {
- err = handleStruct(request, dataValue, prefix, name, fieldPosition, i)
- if err != nil {
- return
- }
- }
- }
- }
- return
- }
- func handleRepeatedParams(request AcsRequest, dataValue reflect.Value, prefix, name, fieldPosition string, index int) (err error) {
- repeatedFieldValue := dataValue.Field(index)
- if repeatedFieldValue.Kind() != reflect.Slice {
- // possible value: {"[]string", "*[]struct"}, we must call Elem() in the last condition
- repeatedFieldValue = repeatedFieldValue.Elem()
- }
- if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
- for m := 0; m < repeatedFieldValue.Len(); m++ {
- elementValue := repeatedFieldValue.Index(m)
- key := prefix + name + "." + strconv.Itoa(m+1)
- if elementValue.Type().Kind().String() == "string" {
- value := elementValue.String()
- err = addParam(request, fieldPosition, key, value)
- if err != nil {
- return
- }
- } else {
- err = flatRepeatedList(elementValue, request, fieldPosition, key+".")
- if err != nil {
- return
- }
- }
- }
- }
- return nil
- }
- func handleStruct(request AcsRequest, dataValue reflect.Value, prefix, name, fieldPosition string, index int) (err error) {
- valueField := dataValue.Field(index)
- if valueField.IsValid() && valueField.String() != "" {
- valueFieldType := valueField.Type()
- for m := 0; m < valueFieldType.NumField(); m++ {
- fieldName := valueFieldType.Field(m).Name
- elementValue := valueField.FieldByName(fieldName)
- key := prefix + name + "." + fieldName
- if elementValue.Type().String() == "[]string" {
- if elementValue.IsNil() {
- continue
- }
- for j := 0; j < elementValue.Len(); j++ {
- err = addParam(request, fieldPosition, key+"."+strconv.Itoa(j+1), elementValue.Index(j).String())
- if err != nil {
- return
- }
- }
- } else {
- if elementValue.Type().Kind().String() == "string" {
- value := elementValue.String()
- err = addParam(request, fieldPosition, key, value)
- if err != nil {
- return
- }
- } else if elementValue.Type().Kind().String() == "struct" {
- err = flatRepeatedList(elementValue, request, fieldPosition, key+".")
- if err != nil {
- return
- }
- } else if !elementValue.IsNil() {
- repeatedFieldValue := elementValue.Elem()
- if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
- for m := 0; m < repeatedFieldValue.Len(); m++ {
- elementValue := repeatedFieldValue.Index(m)
- err = flatRepeatedList(elementValue, request, fieldPosition, key+"."+strconv.Itoa(m+1)+".")
- if err != nil {
- return
- }
- }
- }
- }
- }
- }
- }
- return nil
- }
- func addParam(request AcsRequest, position, name, value string) (err error) {
- if len(value) > 0 {
- switch position {
- case Header:
- request.addHeaderParam(name, value)
- case Query:
- request.addQueryParam(name, value)
- case Path:
- request.addPathParam(name, value)
- case Body:
- request.addFormParam(name, value)
- default:
- errMsg := fmt.Sprintf(errors.UnsupportedParamPositionErrorMessage, position)
- err = errors.NewClientError(errors.UnsupportedParamPositionErrorCode, errMsg, nil)
- }
- }
- return
- }
|