mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 11:18:02 +08:00
ee58255418
* move common used tag from packages to package gtag for maintainability * move common used tag from packages to package gtag for maintainability Co-authored-by: houseme <housemecn@gmail.com>
102 lines
2.6 KiB
Go
102 lines
2.6 KiB
Go
// 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/text/gregex"
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
"github.com/gogf/gf/v2/util/gmeta"
|
|
"github.com/gogf/gf/v2/util/gtag"
|
|
"github.com/gogf/gf/v2/util/gutil"
|
|
)
|
|
|
|
// 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, gtag.Method).String()
|
|
path = gmeta.Get(req, gtag.Path).String()
|
|
)
|
|
if method == "" {
|
|
return gerror.NewCodef(
|
|
gcode.CodeInvalidParameter,
|
|
`no "%s" tag found in request object: %s`,
|
|
gtag.Method, reflect.TypeOf(req).String(),
|
|
)
|
|
}
|
|
if path == "" {
|
|
return gerror.NewCodef(
|
|
gcode.CodeInvalidParameter,
|
|
`no "%s" tag found in request object: %s`,
|
|
gtag.Path, 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.Map(req)
|
|
if len(requestParamsMap) > 0 {
|
|
path, _ = gregex.ReplaceStringFuncMatch(`\{(\w+)\}`, path, func(match []string) string {
|
|
foundKey, foundValue := gutil.MapPossibleItemByKey(requestParamsMap, match[1])
|
|
if foundKey != "" {
|
|
return gconv.String(foundValue)
|
|
}
|
|
return match[0]
|
|
})
|
|
}
|
|
}
|
|
return path
|
|
}
|