diff --git a/go.mod b/go.mod index 404f5f9..0cf0627 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module git.zhangdeman.cn/zhangdeman/network -go 1.23.0 - -toolchain go1.24.1 +go 1.24.1 require ( git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c @@ -14,13 +12,32 @@ require ( ) require ( + git.zhangdeman.cn/gateway/validate v0.0.0-20250324092220-164ea6b3ac40 // indirect + git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20250323125506-1b217c0e4fee // indirect + git.zhangdeman.cn/zhangdeman/json_filter v0.0.0-20250321103029-786c03293a28 // indirect + git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect + git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 // indirect github.com/BurntSushi/toml v1.5.0 // indirect + github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect + github.com/creasty/defaults v1.8.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/go-ini/ini v1.67.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.25.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mozillazg/go-pinyin v0.20.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + golang.org/x/crypto v0.36.0 // indirect golang.org/x/net v0.38.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index b15e4ba..3106c26 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,56 @@ +git.zhangdeman.cn/gateway/validate v0.0.0-20250324092220-164ea6b3ac40 h1:LtTK4adOiI1QBRNPZqyZse8TdV41wRpr4TPHOXzlPJ0= +git.zhangdeman.cn/gateway/validate v0.0.0-20250324092220-164ea6b3ac40/go.mod h1:4/5H+6rOx7/gr6fS8eumTL1HVWIz1l6EslDwquI+6e0= git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c h1:cl3gQGXQpJ8ugDs0C/hQLfcvF4lGBm5BeABLvROFDoM= git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k= +git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20250323125506-1b217c0e4fee h1:ufokPLk1nUKk+N5fDm/uD82OKqQn0EP/CMN6lK+wslM= +git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20250323125506-1b217c0e4fee/go.mod h1:HwmL/Vtn3T9T4w6Gh8RlXRQ5o/3YNGqgLIuwgTJB0Mg= +git.zhangdeman.cn/zhangdeman/json_filter v0.0.0-20250321103029-786c03293a28 h1:wzEv9TXimkXuvjIgLuU+JETmWzj3AjfS3JA2cvU51xM= +git.zhangdeman.cn/zhangdeman/json_filter v0.0.0-20250321103029-786c03293a28/go.mod h1:RHYpM8BsZg9CuK78oY0+/n3g4kHMXk04+Gj1Sfg6E3U= +git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 h1:gUDlQMuJ4xNfP2Abl1Msmpa3fASLWYkNlqDFF/6GN0Y= +git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI= git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI= git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs= git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI= git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI= +git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 h1:zPUoylfJTbc0EcxW+NEzOTBmoeFZ2I/rLFBnEzxb4Wk= +git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740/go.mod h1:1ct92dbVc49pmXusA/iGfcQUJzcYmJ+cjAhgc3sDv1I= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ= +github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg= +github.com/creasty/defaults v1.8.0 h1:z27FJxCAa0JKt3utc0sCImAEb+spPucmKoOdLHvHYKk= +github.com/creasty/defaults v1.8.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8= +github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ= +github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc= github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -27,8 +58,16 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/httpclient/define/request.go b/httpclient/define/request.go index cdc24e9..5a16336 100644 --- a/httpclient/define/request.go +++ b/httpclient/define/request.go @@ -18,9 +18,9 @@ type Request struct { Ctx context.Context `json:"-"` // 请求上下文 PathParam map[string]string `json:"path_param"` // 替换url中的占位符 Body map[string]any `json:"body"` // 请求Body - Header map[string]string `json:"header"` // 请求Header - Cookie map[string]string `json:"cookie"` // 请求Cookie - Query map[string]string `json:"query"` // 请求query + Header map[string]any `json:"header"` // 请求Header + Cookie map[string]any `json:"cookie"` // 请求Cookie + Query map[string]any `json:"query"` // 请求query FullUrl string `json:"full_url"` // 完整的请求URL ContentType string `json:"content_type"` // 请求类型 Method string `json:"method"` // 请求方法 diff --git a/httpclient/mesh/define.go b/httpclient/mesh/define.go index a273e76..c69c62f 100644 --- a/httpclient/mesh/define.go +++ b/httpclient/mesh/define.go @@ -58,11 +58,13 @@ type RequestConfigGroupItemFailBehavior struct { // // Date : 14:23 2025/3/28 type RequestConfigGroupItemParamRule struct { - Location consts.RequestDataLocation `json:"location"` // 参数位置 - Path string `json:"path"` // 参数设置的路径 - Type consts.DataType `json:"type"` // 参数类型 - SourceAlias string `json:"source_alias"` // 数据源请求别名 __COMMON__ 代表从公共参数读取数据 - SourceResultPath string `json:"source_result_path"` // 数据源数据, 从结果中获取的路径 + Location consts.RequestDataLocation `json:"location"` // 参数位置 + Path string `json:"path"` // 参数设置的路径 + Type consts.DataType `json:"type"` // 参数类型 + SourceAlias string `json:"source_alias"` // 数据源请求别名 __COMMON__ 代表从公共参数读取数据 + SourceResultLocation string `json:"source_result_location"` // 数据源请求结果位置 + SourceResultPath string `json:"source_result_path"` // 数据源数据, 从结果中获取的路径 + DefaultValue string `json:"default_value"` // 默认值 } // RequestConfigResultRule 返回值构建规则 diff --git a/httpclient/mesh/mesh.go b/httpclient/mesh/mesh.go index 8a38406..e077de8 100644 --- a/httpclient/mesh/mesh.go +++ b/httpclient/mesh/mesh.go @@ -9,8 +9,13 @@ package mesh import ( "context" + "fmt" + "git.zhangdeman.cn/gateway/validate" + "git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/network/httpclient" "git.zhangdeman.cn/zhangdeman/network/httpclient/define" + "git.zhangdeman.cn/zhangdeman/serialize" + "strings" "sync" ) @@ -47,6 +52,11 @@ func (c *client) Request() *Response { break } } + if c.resp.FinalFailure { + // 请求失败 + return c.resp + } + // 请求成功, 构建返回结果 return c.resp } @@ -65,10 +75,21 @@ func (c *client) doRequest(apiList []*RequestConfigGroupItem) bool { var ( err error httpClient *httpclient.HttpClient + param map[string]map[string]any ) // 初始化一下请求 c.initApiCfg(apiCfg) - // TODO: 构造生成请求参数 + // 构造生成请求参数 + if param, err = c.buildRequestParams(apiCfg); nil != err { + // 构造请求参数失败, 直接返回 + c.resp.ErrorCode = "-500" + c.resp.ErrorMessage = err.Error() + return false + } + apiCfg.RequestCfg.Body = param[consts.RequestDataLocationBody.String()] // body + apiCfg.RequestCfg.Header = param[consts.RequestDataLocationHeader.String()] // header + apiCfg.RequestCfg.Cookie = param[consts.RequestDataLocationCookie.String()] // cookie + apiCfg.RequestCfg.Query = param[consts.RequestDataLocationQuery.String()] // query if httpClient, err = httpclient.NewHttpClient(apiCfg.RequestCfg, apiCfg.CacheInstance); nil != err { // 此处获取客户端实例即发生异常, 忽略一切配置, 直接作为全局失败, 后续也不请求了 c.resp.ErrorCode = "-500" @@ -125,3 +146,39 @@ func (c *client) initApiCfg(apiCfg *RequestConfigGroupItem) { // 每一个请求有独立的context apiCfg.RequestCfg.Ctx = context.WithValue(c.reqCfg.Ctx, "alias", apiCfg.Alias) } + +// buildRequestParams 构建请求参数 location => path: value +func (c *client) buildRequestParams(apiCfg *RequestConfigGroupItem) (map[string]map[string]any, error) { + sourceData := map[string]any{} + for aliasName, itemRes := range c.resp.AliasResultTable { + sourceData[aliasName] = map[string]any{ + consts.ResponseDataLocationBody.String(): itemRes.Body[apiCfg.RequestCfg.DataField], + consts.ResponseDataLocationHeader.String(): itemRes.Header, + consts.ResponseDataLocationCookie.String(): itemRes.Cookie, + } + } + sourceDataByte := serialize.JSON.MarshalForByteIgnoreError(sourceData) + validateRuleList := make([]validate.StructField, 0) + for _, itemParam := range apiCfg.ParamRuleList { + arr := strings.Split(itemParam.Path, ".") + validateRuleList = append(validateRuleList, validate.StructField{ + JsonTag: arr[len(arr)-1], + Type: itemParam.Type, + Required: false, + RuleList: nil, + DefaultValue: itemParam.DefaultValue, + SourcePath: fmt.Sprintf("%v.%v.%v", itemParam.SourceAlias, itemParam.SourceResultLocation, itemParam.SourceResultPath), // TODO : 公共参数特殊处理 + TargetPath: fmt.Sprintf("%v.%v", itemParam.Location, itemParam.Path), + Errmsg: "", + }) + } + buildRes, err := validate.Run(sourceDataByte, validateRuleList) + if nil != err { + return nil, err + } + var d map[string]map[string]any + if err = serialize.JSON.UnmarshalWithNumber(buildRes, &d); nil != err { + return nil, err + } + return d, err +}