Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bcb5bffbc7 | |||
| c87ce79386 | |||
| b9ace42a5b | |||
| 3a75a83be1 | |||
| af66437067 | |||
| e0a739a681 | |||
| d9ff2bfbeb | |||
| fc13b6ebee | |||
| 6355725204 | |||
| b6aa048c4a | |||
| 5da4c33a57 | |||
| 2a316b984d | |||
| fa780870a7 | |||
| 9144ca7f27 | |||
| 174725cf27 |
@@ -0,0 +1,35 @@
|
||||
name: Go CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.13, 1.14, 1.15]
|
||||
|
||||
steps:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build Tea
|
||||
run: go build ./tea
|
||||
- name: Build Util
|
||||
run: go build ./utils
|
||||
|
||||
- name: Test
|
||||
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./tea/... ./utils/...
|
||||
|
||||
- name: CodeCov
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.12.x
|
||||
|
||||
branches: # build only on these branches
|
||||
only:
|
||||
- master
|
||||
|
||||
install:
|
||||
- export GO111MODULE=on
|
||||
|
||||
notifications:
|
||||
webhooks: https://oapi.dingtalk.com/robot/send?access_token=096ed387df243a6d60835aadeccc47165f3813bc7cb81cdd0cfeadfd28e3acc1
|
||||
email: false
|
||||
on_success: change
|
||||
on_failure: always
|
||||
|
||||
script:
|
||||
- go mod tidy
|
||||
- go test -race -coverprofile=coverage.txt -covermode=atomic ./tea/... ./utils/...
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
@@ -4,5 +4,7 @@ go 1.14
|
||||
|
||||
require (
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68
|
||||
github.com/json-iterator/go v1.1.10
|
||||
github.com/modern-go/reflect2 v1.0.1
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+113
-35
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -35,7 +36,7 @@ var hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *
|
||||
}
|
||||
|
||||
var basicTypes = []string{
|
||||
"int", "int64", "float32", "float64", "string", "bool", "uint64",
|
||||
"int", "int16", "int64", "int32", "float32", "float64", "string", "bool", "uint64", "uint32", "uint16",
|
||||
}
|
||||
|
||||
// Verify whether the parameters meet the requirements
|
||||
@@ -68,11 +69,14 @@ type Response struct {
|
||||
|
||||
// SDKError struct is used save error code and message
|
||||
type SDKError struct {
|
||||
Code *string
|
||||
Message *string
|
||||
Data *string
|
||||
Stack *string
|
||||
errMsg *string
|
||||
Code *string
|
||||
StatusCode *int
|
||||
Message *string
|
||||
Data *string
|
||||
Stack *string
|
||||
errMsg *string
|
||||
Description *string
|
||||
AccessDeniedDetail map[string]interface{}
|
||||
}
|
||||
|
||||
// RuntimeObject is used for converting http configuration
|
||||
@@ -85,6 +89,9 @@ type RuntimeObject struct {
|
||||
HttpsProxy *string `json:"httpsProxy" xml:"httpsProxy"`
|
||||
NoProxy *string `json:"noProxy" xml:"noProxy"`
|
||||
MaxIdleConns *int `json:"maxIdleConns" xml:"maxIdleConns"`
|
||||
Key *string `json:"key" xml:"key"`
|
||||
Cert *string `json:"cert" xml:"cert"`
|
||||
CA *string `json:"ca" xml:"ca"`
|
||||
Socks5Proxy *string `json:"socks5Proxy" xml:"socks5Proxy"`
|
||||
Socks5NetWork *string `json:"socks5NetWork" xml:"socks5NetWork"`
|
||||
Listener utils.ProgressListener `json:"listener" xml:"listener"`
|
||||
@@ -123,6 +130,9 @@ func NewRuntimeObject(runtime map[string]interface{}) *RuntimeObject {
|
||||
MaxIdleConns: TransInterfaceToInt(runtime["maxIdleConns"]),
|
||||
Socks5Proxy: TransInterfaceToString(runtime["socks5Proxy"]),
|
||||
Socks5NetWork: TransInterfaceToString(runtime["socks5NetWork"]),
|
||||
Key: TransInterfaceToString(runtime["key"]),
|
||||
Cert: TransInterfaceToString(runtime["cert"]),
|
||||
CA: TransInterfaceToString(runtime["ca"]),
|
||||
}
|
||||
if runtime["listener"] != nil {
|
||||
runtimeObject.Listener = runtime["listener"].(utils.ProgressListener)
|
||||
@@ -173,10 +183,54 @@ func NewSDKError(obj map[string]interface{}) *SDKError {
|
||||
if obj["message"] != nil {
|
||||
err.Message = String(obj["message"].(string))
|
||||
}
|
||||
if obj["description"] != nil {
|
||||
err.Description = String(obj["description"].(string))
|
||||
}
|
||||
if detail := obj["accessDeniedDetail"]; detail != nil {
|
||||
r := reflect.ValueOf(detail)
|
||||
if r.Kind().String() == "map" {
|
||||
res := make(map[string]interface{})
|
||||
tmp := r.MapKeys()
|
||||
for _, key := range tmp {
|
||||
res[key.String()] = r.MapIndex(key).Interface()
|
||||
}
|
||||
err.AccessDeniedDetail = res
|
||||
}
|
||||
}
|
||||
if data := obj["data"]; data != nil {
|
||||
r := reflect.ValueOf(data)
|
||||
if r.Kind().String() == "map" {
|
||||
res := make(map[string]interface{})
|
||||
tmp := r.MapKeys()
|
||||
for _, key := range tmp {
|
||||
res[key.String()] = r.MapIndex(key).Interface()
|
||||
}
|
||||
if statusCode := res["statusCode"]; statusCode != nil {
|
||||
if code, ok := statusCode.(int); ok {
|
||||
err.StatusCode = Int(code)
|
||||
} else if tmp, ok := statusCode.(string); ok {
|
||||
code, err_ := strconv.Atoi(tmp)
|
||||
if err_ == nil {
|
||||
err.StatusCode = Int(code)
|
||||
}
|
||||
} else if code, ok := statusCode.(*int); ok {
|
||||
err.StatusCode = code
|
||||
}
|
||||
}
|
||||
}
|
||||
byt, _ := json.Marshal(data)
|
||||
err.Data = String(string(byt))
|
||||
}
|
||||
|
||||
if statusCode, ok := obj["statusCode"].(int); ok {
|
||||
err.StatusCode = Int(statusCode)
|
||||
} else if status, ok := obj["statusCode"].(string); ok {
|
||||
statusCode, err_ := strconv.Atoi(status)
|
||||
if err_ == nil {
|
||||
err.StatusCode = Int(statusCode)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -187,8 +241,8 @@ func (err *SDKError) SetErrMsg(msg string) {
|
||||
|
||||
func (err *SDKError) Error() string {
|
||||
if err.errMsg == nil {
|
||||
str := fmt.Sprintf("SDKError:\n Code: %s\n Message: %s\n Data: %s\n",
|
||||
StringValue(err.Code), StringValue(err.Message), StringValue(err.Data))
|
||||
str := fmt.Sprintf("SDKError:\n StatusCode: %d\n Code: %s\n Message: %s\n Data: %s\n",
|
||||
IntValue(err.StatusCode), StringValue(err.Code), StringValue(err.Message), StringValue(err.Data))
|
||||
err.SetErrMsg(str)
|
||||
}
|
||||
return StringValue(err.errMsg)
|
||||
@@ -202,7 +256,9 @@ func (err *CastError) Error() string {
|
||||
// Convert is use convert map[string]interface object to struct
|
||||
func Convert(in interface{}, out interface{}) error {
|
||||
byt, _ := json.Marshal(in)
|
||||
err := json.Unmarshal(byt, out)
|
||||
decoder := jsonParser.NewDecoder(bytes.NewReader(byt))
|
||||
decoder.UseNumber()
|
||||
err := decoder.Decode(&out)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -264,20 +320,12 @@ func DoRequest(request *Request, requestRuntime map[string]interface{}) (respons
|
||||
request.Protocol = String(strings.ToLower(StringValue(request.Protocol)))
|
||||
}
|
||||
|
||||
if StringValue(request.Protocol) == "http" {
|
||||
request.Port = Int(80)
|
||||
} else if StringValue(request.Protocol) == "https" {
|
||||
request.Port = Int(443)
|
||||
}
|
||||
|
||||
requestURL := ""
|
||||
request.Domain = request.Headers["host"]
|
||||
matched, _ := regexp.MatchString(":", StringValue(request.Domain))
|
||||
if matched {
|
||||
requestURL = fmt.Sprintf("%s://%s%s", StringValue(request.Protocol), StringValue(request.Domain), StringValue(request.Pathname))
|
||||
} else {
|
||||
requestURL = fmt.Sprintf("%s://%s:%d%s", StringValue(request.Protocol), StringValue(request.Domain), IntValue(request.Port), StringValue(request.Pathname))
|
||||
if request.Port != nil {
|
||||
request.Domain = String(fmt.Sprintf("%s:%d", StringValue(request.Domain), IntValue(request.Port)))
|
||||
}
|
||||
requestURL = fmt.Sprintf("%s://%s%s", StringValue(request.Protocol), StringValue(request.Domain), StringValue(request.Pathname))
|
||||
queryParams := request.Query
|
||||
// sort QueryParams by key
|
||||
q := url.Values{}
|
||||
@@ -367,8 +415,29 @@ func getHttpTransport(req *Request, runtime *RuntimeObject) (*http.Transport, er
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trans.TLSClientConfig = &tls.Config{
|
||||
InsecureSkipVerify: BoolValue(runtime.IgnoreSSL),
|
||||
if strings.ToLower(*req.Protocol) == "https" &&
|
||||
runtime.Key != nil && runtime.Cert != nil {
|
||||
cert, err := tls.X509KeyPair([]byte(StringValue(runtime.Cert)), []byte(StringValue(runtime.Key)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
trans.TLSClientConfig = &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
InsecureSkipVerify: BoolValue(runtime.IgnoreSSL),
|
||||
}
|
||||
if runtime.CA != nil {
|
||||
clientCertPool := x509.NewCertPool()
|
||||
ok := clientCertPool.AppendCertsFromPEM([]byte(StringValue(runtime.CA)))
|
||||
if !ok {
|
||||
return nil, errors.New("Failed to parse root certificate")
|
||||
}
|
||||
trans.TLSClientConfig.RootCAs = clientCertPool
|
||||
}
|
||||
} else {
|
||||
trans.TLSClientConfig = &tls.Config{
|
||||
InsecureSkipVerify: BoolValue(runtime.IgnoreSSL),
|
||||
}
|
||||
}
|
||||
if httpProxy != nil {
|
||||
trans.Proxy = http.ProxyURL(httpProxy)
|
||||
@@ -397,7 +466,7 @@ func getHttpTransport(req *Request, runtime *RuntimeObject) (*http.Transport, er
|
||||
&net.Dialer{
|
||||
Timeout: time.Duration(IntValue(runtime.ConnectTimeout)) * time.Millisecond,
|
||||
DualStack: true,
|
||||
LocalAddr: getLocalAddr(StringValue(runtime.LocalAddr), IntValue(req.Port)),
|
||||
LocalAddr: getLocalAddr(StringValue(runtime.LocalAddr)),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -405,7 +474,7 @@ func getHttpTransport(req *Request, runtime *RuntimeObject) (*http.Transport, er
|
||||
trans.Dial = dialer.Dial
|
||||
}
|
||||
} else {
|
||||
trans.DialContext = setDialContext(runtime, IntValue(req.Port))
|
||||
trans.DialContext = setDialContext(runtime)
|
||||
}
|
||||
return trans, nil
|
||||
}
|
||||
@@ -493,22 +562,20 @@ func getSocks5Proxy(runtime *RuntimeObject) (proxy *url.URL, err error) {
|
||||
return proxy, err
|
||||
}
|
||||
|
||||
func getLocalAddr(localAddr string, port int) (addr *net.TCPAddr) {
|
||||
func getLocalAddr(localAddr string) (addr *net.TCPAddr) {
|
||||
if localAddr != "" {
|
||||
addr = &net.TCPAddr{
|
||||
Port: port,
|
||||
IP: []byte(localAddr),
|
||||
IP: []byte(localAddr),
|
||||
}
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
func setDialContext(runtime *RuntimeObject, port int) func(cxt context.Context, net, addr string) (c net.Conn, err error) {
|
||||
func setDialContext(runtime *RuntimeObject) func(cxt context.Context, net, addr string) (c net.Conn, err error) {
|
||||
return func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
if runtime.LocalAddr != nil && StringValue(runtime.LocalAddr) != "" {
|
||||
netAddr := &net.TCPAddr{
|
||||
Port: port,
|
||||
IP: []byte(StringValue(runtime.LocalAddr)),
|
||||
IP: []byte(StringValue(runtime.LocalAddr)),
|
||||
}
|
||||
return (&net.Dialer{
|
||||
Timeout: time.Duration(IntValue(runtime.ConnectTimeout)) * time.Second,
|
||||
@@ -698,7 +765,9 @@ func structToMap(dataValue reflect.Value) map[string]interface{} {
|
||||
if !fieldValue.IsValid() || fieldValue.IsNil() {
|
||||
continue
|
||||
}
|
||||
if field.Type.Kind().String() == "struct" {
|
||||
if field.Type.String() == "io.Reader" || field.Type.String() == "io.Writer" {
|
||||
continue
|
||||
} else if field.Type.Kind().String() == "struct" {
|
||||
out[name] = structToMap(fieldValue)
|
||||
} else if field.Type.Kind().String() == "ptr" &&
|
||||
field.Type.Elem().Kind().String() == "struct" {
|
||||
@@ -748,10 +817,10 @@ func Retryable(err error) *bool {
|
||||
return Bool(false)
|
||||
}
|
||||
if realErr, ok := err.(*SDKError); ok {
|
||||
code, err := strconv.Atoi(StringValue(realErr.Code))
|
||||
if err != nil {
|
||||
return Bool(true)
|
||||
if realErr.StatusCode == nil {
|
||||
return Bool(false)
|
||||
}
|
||||
code := IntValue(realErr.StatusCode)
|
||||
return Bool(code >= http.StatusInternalServerError)
|
||||
}
|
||||
return Bool(true)
|
||||
@@ -931,7 +1000,8 @@ func checkRequire(field reflect.StructField, valueField reflect.Value) error {
|
||||
func checkPattern(field reflect.StructField, valueField reflect.Value, tag string) error {
|
||||
if valueField.IsValid() && valueField.String() != "" {
|
||||
value := valueField.String()
|
||||
if match, _ := regexp.MatchString(tag, value); !match { // Determines whether the parameter value satisfies the regular expression or not, and throws an error
|
||||
r, _ := regexp.Compile("^" + tag + "$")
|
||||
if match := r.MatchString(value); !match { // Determines whether the parameter value satisfies the regular expression or not, and throws an error
|
||||
return errors.New(value + " is not matched " + tag)
|
||||
}
|
||||
}
|
||||
@@ -1081,3 +1151,11 @@ func Prettify(i interface{}) string {
|
||||
resp, _ := json.MarshalIndent(i, "", " ")
|
||||
return string(resp)
|
||||
}
|
||||
|
||||
func ToInt(a *int32) *int {
|
||||
return Int(int(Int32Value(a)))
|
||||
}
|
||||
|
||||
func ToInt32(a *int) *int32 {
|
||||
return Int32(int32(IntValue(a)))
|
||||
}
|
||||
|
||||
+192
-15
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user