Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d9c5d0857b | |||
| 852924e5df | |||
| 4c13582572 | |||
| d3a7dc916c |
@@ -1,5 +1,7 @@
|
||||
module github.com/alibabacloud-go/tea
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
|
||||
|
||||
+110
-14
@@ -39,7 +39,7 @@ var basicTypes = []string{
|
||||
}
|
||||
|
||||
// Verify whether the parameters meet the requirements
|
||||
var validateParams = []string{"require", "pattern", "maxLength"}
|
||||
var validateParams = []string{"require", "pattern", "maxLength", "minLength", "maximum", "minimum"}
|
||||
|
||||
// CastError is used for cast type fails
|
||||
type CastError struct {
|
||||
@@ -71,6 +71,8 @@ type SDKError struct {
|
||||
Code *string
|
||||
Message *string
|
||||
Data *string
|
||||
Stack *string
|
||||
errMsg *string
|
||||
}
|
||||
|
||||
// RuntimeObject is used for converting http configuration
|
||||
@@ -178,6 +180,19 @@ func NewSDKError(obj map[string]interface{}) *SDKError {
|
||||
return err
|
||||
}
|
||||
|
||||
func (err *SDKError) SetErrMsg(msg string) {
|
||||
err.errMsg = String(msg)
|
||||
}
|
||||
|
||||
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))
|
||||
err.SetErrMsg(str)
|
||||
}
|
||||
return StringValue(err.errMsg)
|
||||
}
|
||||
|
||||
// Return message of CastError
|
||||
func (err *CastError) Error() string {
|
||||
return StringValue(err.Message)
|
||||
@@ -296,7 +311,7 @@ func DoRequest(request *Request, requestRuntime map[string]interface{}) (respons
|
||||
} else {
|
||||
httpRequest.Header[key] = []string{*value}
|
||||
}
|
||||
debugLog("> %s: %s", key, value)
|
||||
debugLog("> %s: %s", key, StringValue(value))
|
||||
}
|
||||
contentlength, _ := strconv.Atoi(StringValue(request.Headers["content-length"]))
|
||||
event := utils.NewProgressEvent(utils.TransferStartedEvent, 0, int64(contentlength), 0)
|
||||
@@ -351,7 +366,7 @@ func getHttpTransport(req *Request, runtime *RuntimeObject) (*http.Transport, er
|
||||
req.Headers["Proxy-Authorization"] = String(basic)
|
||||
}
|
||||
}
|
||||
if runtime.Socks5Proxy != nil {
|
||||
if runtime.Socks5Proxy != nil && StringValue(runtime.Socks5Proxy) != "" {
|
||||
socks5Proxy, err := getSocks5Proxy(runtime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -401,7 +416,7 @@ func putMsgToMap(fieldMap map[string]string, request *http.Request) {
|
||||
|
||||
func getNoProxy(protocol string, runtime *RuntimeObject) []string {
|
||||
var urls []string
|
||||
if runtime.NoProxy != nil {
|
||||
if runtime.NoProxy != nil && StringValue(runtime.NoProxy) != "" {
|
||||
urls = strings.Split(StringValue(runtime.NoProxy), ",")
|
||||
} else if rawurl := os.Getenv("NO_PROXY"); rawurl != "" {
|
||||
urls = strings.Split(rawurl, ",")
|
||||
@@ -438,7 +453,7 @@ func getHttpProxy(protocol, host string, runtime *RuntimeObject) (proxy *url.URL
|
||||
}
|
||||
}
|
||||
if protocol == "https" {
|
||||
if runtime.HttpsProxy != nil {
|
||||
if runtime.HttpsProxy != nil && StringValue(runtime.HttpsProxy) != "" {
|
||||
proxy, err = url.Parse(StringValue(runtime.HttpsProxy))
|
||||
} else if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" {
|
||||
proxy, err = url.Parse(rawurl)
|
||||
@@ -446,7 +461,7 @@ func getHttpProxy(protocol, host string, runtime *RuntimeObject) (proxy *url.URL
|
||||
proxy, err = url.Parse(rawurl)
|
||||
}
|
||||
} else {
|
||||
if runtime.HttpProxy != nil {
|
||||
if runtime.HttpProxy != nil && StringValue(runtime.HttpProxy) != "" {
|
||||
proxy, err = url.Parse(StringValue(runtime.HttpProxy))
|
||||
} else if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" {
|
||||
proxy, err = url.Parse(rawurl)
|
||||
@@ -459,7 +474,7 @@ func getHttpProxy(protocol, host string, runtime *RuntimeObject) (proxy *url.URL
|
||||
}
|
||||
|
||||
func getSocks5Proxy(runtime *RuntimeObject) (proxy *url.URL, err error) {
|
||||
if runtime.Socks5Proxy != nil {
|
||||
if runtime.Socks5Proxy != nil && StringValue(runtime.Socks5Proxy) != "" {
|
||||
proxy, err = url.Parse(StringValue(runtime.Socks5Proxy))
|
||||
}
|
||||
return proxy, err
|
||||
@@ -477,7 +492,7 @@ func getLocalAddr(localAddr string, port int) (addr *net.TCPAddr) {
|
||||
|
||||
func setDialContext(runtime *RuntimeObject, port int) 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 {
|
||||
if runtime.LocalAddr != nil && StringValue(runtime.LocalAddr) != "" {
|
||||
netAddr := &net.TCPAddr{
|
||||
Port: port,
|
||||
IP: []byte(StringValue(runtime.LocalAddr)),
|
||||
@@ -495,11 +510,6 @@ func setDialContext(runtime *RuntimeObject, port int) func(cxt context.Context,
|
||||
}
|
||||
}
|
||||
|
||||
func (err *SDKError) Error() string {
|
||||
return fmt.Sprintf("SDKError:\n Code: %s\n Message: %s\n Data: %s\n",
|
||||
StringValue(err.Code), StringValue(err.Message), StringValue(err.Data))
|
||||
}
|
||||
|
||||
func ToObject(obj interface{}) map[string]interface{} {
|
||||
result := make(map[string]interface{})
|
||||
byt, _ := json.Marshal(obj)
|
||||
@@ -650,6 +660,9 @@ func structToMap(dataValue reflect.Value) map[string]interface{} {
|
||||
return out
|
||||
}
|
||||
if dataValue.Kind().String() == "ptr" {
|
||||
if dataValue.IsNil() {
|
||||
return out
|
||||
}
|
||||
dataValue = dataValue.Elem()
|
||||
}
|
||||
if !dataValue.IsValid() {
|
||||
@@ -664,9 +677,12 @@ func structToMap(dataValue reflect.Value) map[string]interface{} {
|
||||
name, containsNameTag := field.Tag.Lookup("json")
|
||||
if !containsNameTag {
|
||||
name = field.Name
|
||||
} else {
|
||||
strs := strings.Split(name, ",")
|
||||
name = strs[0]
|
||||
}
|
||||
fieldValue := dataValue.FieldByName(field.Name)
|
||||
if !fieldValue.IsValid() {
|
||||
if !fieldValue.IsValid() || fieldValue.IsNil() {
|
||||
continue
|
||||
}
|
||||
if field.Type.Kind().String() == "struct" {
|
||||
@@ -837,6 +853,27 @@ func validatePtr(elementValue reflect.Value, containsregexpTag bool, tag, tagNam
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if tagName == "minLength" {
|
||||
err := checkMinLength(elementValue.Elem(), tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if tagName == "maximum" {
|
||||
err := checkMaximum(elementValue.Elem(), tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if tagName == "minimum" {
|
||||
err := checkMinimum(elementValue.Elem(), tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := validate(elementValue)
|
||||
@@ -849,6 +886,8 @@ func validatePtr(elementValue reflect.Value, containsregexpTag bool, tag, tagNam
|
||||
|
||||
func checkRequire(field reflect.StructField, valueField reflect.Value) error {
|
||||
name, _ := field.Tag.Lookup("json")
|
||||
strs := strings.Split(name, ",")
|
||||
name = strs[0]
|
||||
if !valueField.IsNil() && valueField.IsValid() {
|
||||
return nil
|
||||
}
|
||||
@@ -883,6 +922,63 @@ func checkMaxLength(valueField reflect.Value, tag string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkMinLength(valueField reflect.Value, tag string) error {
|
||||
if valueField.IsValid() {
|
||||
minLength, err := strconv.Atoi(tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
length := valueField.Len()
|
||||
if valueField.Kind().String() == "string" {
|
||||
length = strings.Count(valueField.String(), "") - 1
|
||||
}
|
||||
if minLength > length {
|
||||
errMsg := fmt.Sprintf("Length of %s is less than %d", valueField.String(), minLength)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkMaximum(valueField reflect.Value, tag string) error {
|
||||
if valueField.IsValid() && valueField.String() != "" {
|
||||
maximum, err := strconv.ParseFloat(tag, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
byt, _ := json.Marshal(valueField.Interface())
|
||||
num, err := strconv.ParseFloat(string(byt), 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maximum < num {
|
||||
errMsg := fmt.Sprintf("%f is greater than %f", num, maximum)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkMinimum(valueField reflect.Value, tag string) error {
|
||||
if valueField.IsValid() && valueField.String() != "" {
|
||||
minimum, err := strconv.ParseFloat(tag, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
byt, _ := json.Marshal(valueField.Interface())
|
||||
num, err := strconv.ParseFloat(string(byt), 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if minimum > num {
|
||||
errMsg := fmt.Sprintf("%f is less than %f", num, minimum)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Determines whether realType is in filterTypes
|
||||
func isFilterType(realType string, filterTypes []string) bool {
|
||||
for _, value := range filterTypes {
|
||||
|
||||
+85
-26
@@ -18,8 +18,8 @@ import (
|
||||
)
|
||||
|
||||
type test struct {
|
||||
Key string `json:"key"`
|
||||
Body []byte `json:"body"`
|
||||
Key string `json:"key,omitempty"`
|
||||
Body []byte `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
type PrettifyTest struct {
|
||||
@@ -46,17 +46,34 @@ var runtimeObj = map[string]interface{}{
|
||||
}
|
||||
|
||||
type validateTest struct {
|
||||
Num *int `json:"num" require:"true"`
|
||||
Name *string `json:"name" maxLength:"4"`
|
||||
Str *string `json:"str" pattern:"^[a-d]*$" maxLength:"4"`
|
||||
Test *errLength `json:"test"`
|
||||
List []*string `json:"list" pattern:"^[a-d]*$" maxLength:"4"`
|
||||
Num1 *int `json:"num1,omitempty" require:"true" minimum:"2"`
|
||||
Num2 *int `json:"num2,omitempty" maximum:"6"`
|
||||
Name1 *string `json:"name1,omitempty" maxLength:"4"`
|
||||
Name2 *string `json:"name2,omitempty" minLength:"2"`
|
||||
Str *string `json:"str,omitempty" pattern:"^[a-d]*$" maxLength:"4"`
|
||||
MaxLength *errMaxLength `json:"MaxLength,omitempty"`
|
||||
MinLength *errMinLength `json:"MinLength,omitempty"`
|
||||
Maximum *errMaximum `json:"Maximum,omitempty"`
|
||||
Minimum *errMinimum `json:"Minimum,omitempty"`
|
||||
List []*string `json:"list,omitempty" pattern:"^[a-d]*$" maxLength:"4"`
|
||||
}
|
||||
|
||||
type errLength struct {
|
||||
type errMaxLength struct {
|
||||
Num *int `json:"num" maxLength:"a"`
|
||||
}
|
||||
|
||||
type errMinLength struct {
|
||||
Num *int `json:"num" minLength:"a"`
|
||||
}
|
||||
|
||||
type errMaximum struct {
|
||||
Num *int `json:"num" maximum:"a"`
|
||||
}
|
||||
|
||||
type errMinimum struct {
|
||||
Num *int `json:"num" minimum:"a"`
|
||||
}
|
||||
|
||||
type Progresstest struct {
|
||||
}
|
||||
|
||||
@@ -204,12 +221,12 @@ func TestMerge(t *testing.T) {
|
||||
}
|
||||
|
||||
type Test struct {
|
||||
Msg *string `json:"Msg"`
|
||||
Cast *CastError `json:"Cast"`
|
||||
ListPtr []*string `json:"ListPtr"`
|
||||
List []string `json:"List"`
|
||||
CastList []CastError `json:"CastList"`
|
||||
CastListPtr []*CastError `json:"CastListPtr"`
|
||||
Msg *string `json:"Msg,omitempty"`
|
||||
Cast *CastError `json:"Cast,omitempty"`
|
||||
ListPtr []*string `json:"ListPtr,omitempty"`
|
||||
List []string `json:"List,omitempty"`
|
||||
CastList []CastError `json:"CastList,omitempty"`
|
||||
CastListPtr []*CastError `json:"CastListPtr,omitempty"`
|
||||
}
|
||||
|
||||
func TestToMap(t *testing.T) {
|
||||
@@ -349,7 +366,7 @@ func Test_DoRequest(t *testing.T) {
|
||||
runtimeObj["httpsProxy"] = "# #%gfdf"
|
||||
resp, err = DoRequest(request, runtimeObj)
|
||||
utils.AssertNil(t, resp)
|
||||
utils.AssertEqual(t, `parse # #%gfdf: invalid URL escape "%gf"`, err.Error())
|
||||
utils.AssertContains(t, err.Error(), `invalid URL escape "%gf"`)
|
||||
|
||||
request.Pathname = String("?log")
|
||||
request.Headers["tea"] = String("")
|
||||
@@ -366,7 +383,7 @@ func Test_DoRequest(t *testing.T) {
|
||||
runtimeObj["socks5Proxy"] = "# #%gfdf"
|
||||
resp, err = DoRequest(request, runtimeObj)
|
||||
utils.AssertNil(t, resp)
|
||||
utils.AssertEqual(t, `parse # #%gfdf: invalid URL escape "%gf"`, err.Error())
|
||||
utils.AssertContains(t, err.Error(), ` invalid URL escape "%gf"`)
|
||||
|
||||
hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
|
||||
return func(req *http.Request) (*http.Response, error) {
|
||||
@@ -528,9 +545,9 @@ func Test_ToString(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_Validate(t *testing.T) {
|
||||
num := 1
|
||||
num := 3
|
||||
config := &validateTest{
|
||||
Num: &num,
|
||||
Num1: &num,
|
||||
}
|
||||
err := Validate(config)
|
||||
utils.AssertNil(t, err)
|
||||
@@ -541,10 +558,11 @@ func Test_validate(t *testing.T) {
|
||||
err := validate(reflect.ValueOf(test))
|
||||
utils.AssertNil(t, err)
|
||||
|
||||
num := 1
|
||||
num := 3
|
||||
str0, str1 := "abc", "abcddd"
|
||||
val := &validateTest{
|
||||
Num: &num,
|
||||
Num1: &num,
|
||||
Num2: &num,
|
||||
Str: &str0,
|
||||
List: []*string{&str0},
|
||||
}
|
||||
@@ -556,15 +574,15 @@ func Test_validate(t *testing.T) {
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, "Length of abcddd is more than 4", err.Error())
|
||||
|
||||
val.Num = nil
|
||||
val.Num1 = nil
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, "num should be setted", err.Error())
|
||||
utils.AssertEqual(t, "num1 should be setted", err.Error())
|
||||
|
||||
val.Name = String("最大长度")
|
||||
val.Name1 = String("最大长度")
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, "num should be setted", err.Error())
|
||||
utils.AssertEqual(t, "num1 should be setted", err.Error())
|
||||
|
||||
val.Num = &num
|
||||
val.Num1 = &num
|
||||
val.Str = &str0
|
||||
val.List = []*string{&str1}
|
||||
err = validate(reflect.ValueOf(val))
|
||||
@@ -581,11 +599,52 @@ func Test_validate(t *testing.T) {
|
||||
|
||||
val.Str = &str0
|
||||
val.List = []*string{&str0}
|
||||
val.Test = &errLength{
|
||||
val.MaxLength = &errMaxLength{
|
||||
Num: &num,
|
||||
}
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, `strconv.Atoi: parsing "a": invalid syntax`, err.Error())
|
||||
|
||||
val.MaxLength = nil
|
||||
val.MinLength = &errMinLength{
|
||||
Num: &num,
|
||||
}
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, `strconv.Atoi: parsing "a": invalid syntax`, err.Error())
|
||||
|
||||
val.MinLength = nil
|
||||
val.Maximum = &errMaximum{
|
||||
Num: &num,
|
||||
}
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, `strconv.ParseFloat: parsing "a": invalid syntax`, err.Error())
|
||||
|
||||
val.Maximum = nil
|
||||
val.Minimum = &errMinimum{
|
||||
Num: &num,
|
||||
}
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, `strconv.ParseFloat: parsing "a": invalid syntax`, err.Error())
|
||||
|
||||
val.Minimum = nil
|
||||
val.Num2 = Int(10)
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, `10.000000 is greater than 6.000000`, err.Error())
|
||||
|
||||
val.Num2 = nil
|
||||
val.Name1 = String("maxLengthTouch")
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, `Length of maxLengthTouch is more than 4`, err.Error())
|
||||
|
||||
val.Name1 = nil
|
||||
val.Name2 = String("")
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, `Length of is less than 2`, err.Error())
|
||||
|
||||
val.Name2 = nil
|
||||
val.Num1 = Int(0)
|
||||
err = validate(reflect.ValueOf(val))
|
||||
utils.AssertEqual(t, `0.000000 is less than 2.000000`, err.Error())
|
||||
}
|
||||
|
||||
func Test_Prettify(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user