Skip to content

Commit

Permalink
feat: Support extended response handler. Fixes gogf#3539
Browse files Browse the repository at this point in the history
Signed-off-by: oninowang <oninowang@tencent.com>
  • Loading branch information
jswxstw authored and oninowang committed Apr 24, 2024
1 parent aa6d83f commit f5b610a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 34 deletions.
55 changes: 55 additions & 0 deletions contrib/sdk/httpclient/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package httpclient

import (
"context"
"encoding/json"

"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/gclient"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/glog"
)

type IHandler interface {
HandleResponse(ctx context.Context, res *gclient.Response, out interface{}) error
}

// DefaultHandler handle ghttp.DefaultHandlerResponse of json format.
type DefaultHandler struct {
Logger *glog.Logger
RawDump bool
}

func NewDefaultHandler(config Config) *DefaultHandler {
return &DefaultHandler{
Logger: config.Logger,
RawDump: config.RawDump,
}
}

func (h DefaultHandler) HandleResponse(ctx context.Context, res *gclient.Response, out interface{}) error {
defer res.Close()
if h.RawDump {
h.Logger.Debugf(ctx, "raw request&response:\n%s", res.Raw())
}
var (
responseBytes = res.ReadAll()
result = ghttp.DefaultHandlerResponse{
Data: out,
}
)
if !json.Valid(responseBytes) {
return gerror.Newf(`invalid response content: %s`, responseBytes)
}
if err := json.Unmarshal(responseBytes, &result); err != nil {
return gerror.Wrapf(err, `json.Unmarshal failed with content:%s`, responseBytes)
}
if result.Code != gcode.CodeOK.Code() {
return gerror.NewCode(
gcode.New(result.Code, result.Message, nil),
result.Message,
)
}
return nil
}
44 changes: 10 additions & 34 deletions contrib/sdk/httpclient/httpclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ package httpclient

import (
"context"
"encoding/json"
"net/http"

"github.com/gogf/gf/v2/encoding/gurl"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/gclient"
"github.com/gogf/gf/v2/net/ghttp"
Expand All @@ -27,7 +25,7 @@ import (
// Client is an http client for SDK.
type Client struct {
*gclient.Client
config Config
IHandler
}

// New creates and returns an http client for SDK.
Expand All @@ -36,36 +34,14 @@ func New(config Config) *Client {
if client == nil {
client = gclient.New()
}
return &Client{
Client: client,
config: config,
}
}

func (c *Client) handleResponse(ctx context.Context, res *gclient.Response, out interface{}) error {
if c.config.RawDump {
c.config.Logger.Debugf(ctx, "raw request&response:\n%s", res.Raw())
handler := config.Handler
if handler == nil {
handler = NewDefaultHandler(config)
}

var (
responseBytes = res.ReadAll()
result = ghttp.DefaultHandlerResponse{
Data: out,
}
)
if !json.Valid(responseBytes) {
return gerror.Newf(`invalid response content: %s`, responseBytes)
}
if err := json.Unmarshal(responseBytes, &result); err != nil {
return gerror.Wrapf(err, `json.Unmarshal failed with content:%s`, responseBytes)
}
if result.Code != gcode.CodeOK.Code() {
return gerror.NewCode(
gcode.New(result.Code, result.Message, nil),
result.Message,
)
return &Client{
Client: client.Prefix(config.URL),
IHandler: handler,
}
return nil
}

// Request sends request to service by struct object `req`, and receives response to struct object `res`.
Expand All @@ -83,20 +59,20 @@ func (c *Client) Request(ctx context.Context, req, res interface{}) error {
if err != nil {
return err
}
return c.handleResponse(ctx, result, res)
return c.HandleResponse(ctx, result, res)
}
}

// Get sends a request using GET method.
func (c *Client) Get(ctx context.Context, path string, in, out interface{}) error {
if urlParams := ghttp.BuildParams(in); urlParams != "" {
path += "?" + ghttp.BuildParams(in)
path += "?" + urlParams
}
res, err := c.ContentJson().Get(ctx, c.handlePath(path, in))
if err != nil {
return gerror.Wrap(err, `http request failed`)
}
return c.handleResponse(ctx, res, out)
return c.HandleResponse(ctx, res, out)
}

func (c *Client) handlePath(path string, in interface{}) string {
Expand Down
1 change: 1 addition & 0 deletions contrib/sdk/httpclient/httpclient_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
type Config struct {
URL string `v:"required"` // Service address. Eg: user.svc.local, http://user.svc.local
Client *gclient.Client // Custom underlying client.
Handler IHandler // Custom response handler.
Logger *glog.Logger // Custom logger.
RawDump bool // Whether auto dump request&response in stdout.
}

0 comments on commit f5b610a

Please sign in to comment.