github.com/gogf/gf/v2@v2.7.4/net/gclient/gclient_request_obj.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gclient 8 9 import ( 10 "context" 11 "net/http" 12 "reflect" 13 14 "github.com/gogf/gf/v2/errors/gcode" 15 "github.com/gogf/gf/v2/errors/gerror" 16 "github.com/gogf/gf/v2/text/gregex" 17 "github.com/gogf/gf/v2/text/gstr" 18 "github.com/gogf/gf/v2/util/gconv" 19 "github.com/gogf/gf/v2/util/gmeta" 20 "github.com/gogf/gf/v2/util/gtag" 21 "github.com/gogf/gf/v2/util/gutil" 22 ) 23 24 // DoRequestObj does HTTP request using standard request/response object. 25 // The request object `req` is defined like: 26 // 27 // type UseCreateReq struct { 28 // g.Meta `path:"/user" method:"put"` 29 // // other fields.... 30 // } 31 // 32 // The response object `res` should be a pointer type. It automatically converts result 33 // to given object `res` is success. 34 // 35 // Example: 36 // var ( 37 // 38 // req = UseCreateReq{} 39 // res *UseCreateRes 40 // 41 // ) 42 // 43 // err := DoRequestObj(ctx, req, &res) 44 func (c *Client) DoRequestObj(ctx context.Context, req, res interface{}) error { 45 var ( 46 method = gmeta.Get(req, gtag.Method).String() 47 path = gmeta.Get(req, gtag.Path).String() 48 ) 49 if method == "" { 50 return gerror.NewCodef( 51 gcode.CodeInvalidParameter, 52 `no "%s" tag found in request object: %s`, 53 gtag.Method, reflect.TypeOf(req).String(), 54 ) 55 } 56 if path == "" { 57 return gerror.NewCodef( 58 gcode.CodeInvalidParameter, 59 `no "%s" tag found in request object: %s`, 60 gtag.Path, reflect.TypeOf(req).String(), 61 ) 62 } 63 path = c.handlePathForObjRequest(path, req) 64 switch gstr.ToUpper(method) { 65 case 66 http.MethodGet, 67 http.MethodPut, 68 http.MethodPost, 69 http.MethodDelete, 70 http.MethodHead, 71 http.MethodPatch, 72 http.MethodConnect, 73 http.MethodOptions, 74 http.MethodTrace: 75 if result := c.RequestVar(ctx, method, path, req); res != nil && !result.IsEmpty() { 76 return result.Scan(res) 77 } 78 return nil 79 80 default: 81 return gerror.Newf(`invalid HTTP method "%s"`, method) 82 } 83 } 84 85 // handlePathForObjRequest replaces parameters in `path` with parameters from request object. 86 // Eg: 87 // /order/{id} -> /order/1 88 // /user/{name} -> /order/john 89 func (c *Client) handlePathForObjRequest(path string, req interface{}) string { 90 if gstr.Contains(path, "{") { 91 requestParamsMap := gconv.Map(req) 92 if len(requestParamsMap) > 0 { 93 path, _ = gregex.ReplaceStringFuncMatch(`\{(\w+)\}`, path, func(match []string) string { 94 foundKey, foundValue := gutil.MapPossibleItemByKey(requestParamsMap, match[1]) 95 if foundKey != "" { 96 return gconv.String(foundValue) 97 } 98 return match[0] 99 }) 100 } 101 } 102 return path 103 }