Compare commits

...

5 Commits

Author SHA1 Message Date
wb-wzc505509 8918f7f891 fix timeout error 2020-07-08 17:20:59 +08:00
wb-wzc505509 29a23a75ba add recover 2020-07-06 10:25:53 +08:00
wb-wzc505509 d9c5d0857b add SetErrMsg to SDKError 2020-07-03 13:21:52 +08:00
wb-wzc505509 852924e5df fix the error caused by omitempty 2020-06-22 13:03:43 +08:00
wenzuochao 4c13582572 support validate minLength minimum maxmum 2020-05-13 14:31:45 +08:00
3 changed files with 215 additions and 35 deletions
+2
View File
@@ -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
+114 -9
View File
@@ -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,20 @@ func NewSDKError(obj map[string]interface{}) *SDKError {
return err
}
// Set ErrMsg by msg
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)
@@ -190,6 +206,14 @@ func Convert(in interface{}, out interface{}) error {
return err
}
// Convert is use convert map[string]interface object to struct
func Recover(in interface{}) error {
if in == nil {
return nil
}
return errors.New(fmt.Sprint(in))
}
// ReadBody is used read response body
func (response *Response) ReadBody() (body []byte, err error) {
defer response.Body.Close()
@@ -283,7 +307,7 @@ func DoRequest(request *Request, requestRuntime map[string]interface{}) (respons
if err != nil {
return nil, err
}
client.httpClient.Timeout = time.Duration(IntValue(runtimeObject.ConnectTimeout)) * time.Second
client.httpClient.Timeout = time.Duration(IntValue(runtimeObject.ReadTimeout)) * time.Millisecond
client.httpClient.Transport = trans
client.ifInit = true
}
@@ -367,7 +391,7 @@ func getHttpTransport(req *Request, runtime *RuntimeObject) (*http.Transport, er
}
dialer, err := proxy.SOCKS5(strings.ToLower(StringValue(runtime.Socks5NetWork)), socks5Proxy.String(), auth,
&net.Dialer{
Timeout: time.Duration(IntValue(runtime.ConnectTimeout)) * time.Second,
Timeout: time.Duration(IntValue(runtime.ConnectTimeout)) * time.Millisecond,
DualStack: true,
LocalAddr: getLocalAddr(StringValue(runtime.LocalAddr), IntValue(req.Port)),
})
@@ -495,11 +519,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 +669,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 +686,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 +862,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 +895,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 +931,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 {
+99 -26
View File
@@ -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 {
}
@@ -141,6 +158,9 @@ func TestSDKError(t *testing.T) {
})
utils.AssertNotNil(t, err)
utils.AssertEqual(t, "SDKError:\n Code: code\n Message: message\n Data: {\"hostId\":\"github.com/alibabacloud/tea\",\"httpCode\":\"404\",\"requestId\":\"dfadfa32cgfdcasd4313\"}\n", err.Error())
err.SetErrMsg("test")
utils.AssertEqual(t, "test", err.Error())
}
func TestSDKErrorCode404(t *testing.T) {
@@ -204,12 +224,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 +369,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 +386,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,23 +548,35 @@ 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)
}
func Test_Recover(t *testing.T) {
err := Recover(nil)
utils.AssertNil(t, err)
defer func() {
if r := Recover(recover()); r != nil {
utils.AssertEqual(t, "test", r.Error())
}
}()
panic("test")
}
func Test_validate(t *testing.T) {
var test *validateTest
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 +588,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 +613,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) {