add DoRequestObj function for gclient.Client

This commit is contained in:
John Guo
2022-06-15 16:28:17 +08:00
parent 481c50f233
commit babc69e13d
3 changed files with 108 additions and 6 deletions

View File

@ -79,13 +79,17 @@ func New() *Client {
func (c *Client) Clone() *Client {
newClient := New()
*newClient = *c
newClient.header = make(map[string]string)
newClient.cookies = make(map[string]string)
for k, v := range c.header {
newClient.header[k] = v
if len(c.header) > 0 {
newClient.header = make(map[string]string)
for k, v := range c.header {
newClient.header[k] = v
}
}
for k, v := range c.cookies {
newClient.cookies[k] = v
if len(c.cookies) > 0 {
newClient.cookies = make(map[string]string)
for k, v := range c.cookies {
newClient.cookies[k] = v
}
}
return newClient
}

View File

@ -12,6 +12,9 @@ import (
// Prefix is a chaining function,
// which sets the URL prefix for next request of this client.
// Eg:
// Prefix("http://127.0.0.1:8199/api/v1")
// Prefix("http://127.0.0.1:8199/api/v2")
func (c *Client) Prefix(prefix string) *Client {
newClient := c.Clone()
newClient.SetPrefix(prefix)

View File

@ -0,0 +1,95 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gclient
import (
"context"
"net/http"
"reflect"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/goai"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gmeta"
)
// DoRequestObj does HTTP request using standard request/response object.
// The request object `req` is defined like:
// type UseCreateReq struct {
// g.Meta `path:"/user" method:"put"`
// // other fields....
// }
// The response object `res` should be a pointer type. It automatically converts result
// to given object `res` is success.
// Eg:
// var (
// req = UseCreateReq{}
// res *UseCreateRes
// )
// DoRequestObj(ctx, req, &res)
func (c *Client) DoRequestObj(ctx context.Context, req, res interface{}) error {
var (
method = gmeta.Get(req, goai.TagNameMethod).String()
path = gmeta.Get(req, goai.TagNamePath).String()
)
if method == "" {
return gerror.NewCodef(
gcode.CodeInvalidParameter,
`no "%s" tag found in request object: %s`,
goai.TagNameMethod, reflect.TypeOf(req).String(),
)
}
if path == "" {
return gerror.NewCodef(
gcode.CodeInvalidParameter,
`no "%s" tag found in request object: %s`,
goai.TagNamePath, reflect.TypeOf(req).String(),
)
}
path = c.handlePathForObjRequest(path, req)
switch gstr.ToUpper(method) {
case
http.MethodGet,
http.MethodPut,
http.MethodPost,
http.MethodDelete,
http.MethodHead,
http.MethodPatch,
http.MethodConnect,
http.MethodOptions,
http.MethodTrace:
if result := c.RequestVar(ctx, method, path, req); res != nil && !result.IsEmpty() {
return result.Scan(res)
}
return nil
default:
return gerror.Newf(`invalid HTTP method "%s"`, method)
}
}
// handlePathForObjRequest replaces parameters in `path` with parameters from request object.
// Eg:
// /order/{id} -> /order/1
// /user/{name} -> /order/john
func (c *Client) handlePathForObjRequest(path string, req interface{}) string {
if gstr.Contains(path, "{") {
requestParamsMap := gconv.MapStrStr(req)
if len(requestParamsMap) > 0 {
path, _ = gregex.ReplaceStringFuncMatch(`\{(\w+)\}`, path, func(match []string) string {
if v, ok := requestParamsMap[match[1]]; ok {
return v
}
return match[1]
})
}
}
return path
}