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  }