Skip to content

Commit da0360b

Browse files
author
dj
committed
Merge branch 'feature-filter' into dev
2 parents d18a3c9 + ea30e68 commit da0360b

File tree

9 files changed

+151
-35
lines changed

9 files changed

+151
-35
lines changed

conf/discover.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,21 @@ type (
2121
DiscoverClientConf
2222
}
2323
TransferConf struct {
24-
Type string `json:",default=httpc"` //httpc,resty
25-
Rety RertyConf `json:",optional"`
24+
Type string `json:",default=resty"` //httpc,resty
25+
Resty RestyConf `json:",optional"`
2626
Httpc HttpcConf `json:",optional"`
2727
}
2828

2929
HttpcConf struct {
3030
}
3131

32-
RertyConf struct {
33-
Agent string `json:",optional"`
32+
RestyConf struct {
33+
Agent string `json:",optional"` //浏览器代理
3434
AllowGetMethodPayload bool `json:",default=false"`
3535
Token string `json:",optional"`
3636
Debug bool `json:",default=false"`
3737
Timeout int64 `json:",default=0"`
3838
Header map[string]string `json:",optional"`
39+
Trace bool `json:",default=false"`
3940
}
4041
)

example/test/etc/test_api.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ HelloDiscoverConf:
2020
Resolver: consul
2121
Transfer:
2222
Type: resty
23-
Rety:
23+
Resty:
2424
Debug: true
25+
Trace: true
2526
Header:
2627
agent: linux
2728
Consul:

factory/client.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ type Client interface {
2525
}
2626

2727
type (
28-
restDiscoverClientOption func(*restDiscoverClient)
29-
restDiscoverClient struct {
28+
restDiscoverClient struct {
3029
config conf.DiscoverClientConf
3130
base []string
3231
service httpc.Service
@@ -57,7 +56,7 @@ func NewRestDiscoverClient(destination string, c conf.DiscoverClientConf, opts .
5756
c.Name = uuid.NewString()
5857
}
5958
if c.Transfer.Type == "resty" {
60-
transfer = rest.NewRestResty(c.Transfer, opts...)
59+
transfer = rest.NewRestResty(c.Name, c.Transfer, opts...)
6160
} else {
6261
//default
6362
transfer = rest.NewRestHttpc(c.Name, opts...)
@@ -88,6 +87,7 @@ func NewRestDiscoverClientWithService(destination string, c conf.DiscoverClientC
8887
restDiscoverClientInstance.subscriber = subscriber2.NewSubscriberConsul(c)
8988
break
9089
case "endpoint":
90+
//直连
9191
if 0 == len(c.Hosts) {
9292
c.Hosts = []string{
9393
destination,

factory/rest/option.go

+1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
package rest
88

99
type (
10+
// RestOption any
1011
RestOption func(v interface{})
1112
)

factory/rest/payload.go

+11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// @author: mengdj<[email protected]>
77
package rest
88

9+
//
910
//go:generate requestgen -type RestPayload -tags json -output payload_requestgen.go
1011
type RestPayload struct {
1112
//request object
@@ -18,3 +19,13 @@ func (r *RestPayload) Reset() {
1819
r.Request = nil
1920
r.Response = nil
2021
}
22+
23+
func (r *RestPayload) SetRequest(req interface{}) *RestPayload {
24+
r.Request = req
25+
return r
26+
}
27+
28+
func (r *RestPayload) SetResponse(resp interface{}) *RestPayload {
29+
r.Response = resp
30+
return r
31+
}

factory/rest/rest_httpc.go

+27-7
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,55 @@ import (
1414
)
1515

1616
type (
17-
restHttpcOption = httpc.Option
18-
restHttpc struct {
17+
HttpcBeforeRequest func(ctx context.Context, url string, data interface{}) (interface{}, error)
18+
restHttpc struct {
1919
httpc.Service
20+
beforeRequest HttpcBeforeRequest
2021
}
2122
)
2223

23-
func (rds restHttpc) Do(ctx context.Context, method, url string, data interface{}) (*http.Response, error) {
24+
func (rds *restHttpc) Do(ctx context.Context, method, url string, data interface{}) (*http.Response, error) {
2425
var (
25-
payload, _ = data.(RestPayload)
26+
payload, _ = data.(*RestPayload)
2627
resp *http.Response
2728
err error
2829
)
30+
if nil != rds.Service {
31+
//before
32+
if payload.Request, err = rds.beforeRequest(ctx, url, data); nil != err {
33+
return nil, err
34+
}
35+
}
2936
if resp, err = rds.Service.Do(ctx, method, url, payload.Request); nil != err {
3037
return nil, err
3138
}
3239
if nil != payload.Response {
40+
//json
3341
if err = jsonx.UnmarshalFromReader(resp.Body, payload.Response); nil != err {
3442
return nil, err
3543
}
3644
}
3745
return resp, err
3846
}
3947

40-
func (rds restHttpc) DoRequest(r *http.Request) (*http.Response, error) {
48+
func (rds *restHttpc) DoRequest(r *http.Request) (*http.Response, error) {
4149
return rds.Service.DoRequest(r)
4250
}
4351

52+
func WithHttpcBeforeRequest(fn HttpcBeforeRequest) RestOption {
53+
return func(v interface{}) {
54+
if target, ok := v.(*restHttpc); ok {
55+
target.beforeRequest = fn
56+
}
57+
}
58+
}
4459
func NewRestHttpc(name string, opts ...RestOption) httpc.Service {
45-
return &restHttpc{
46-
Service: httpc.NewServiceWithClient(name, http.DefaultClient),
60+
r := &restHttpc{
61+
Service: httpc.NewServiceWithClient(name, http.DefaultClient),
62+
beforeRequest: nil,
63+
}
64+
for _, opt := range opts {
65+
opt(r)
4766
}
67+
return r
4868
}

factory/rest/rest_resty.go

+97-20
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ import (
1212
"github.com/go-resty/resty/v2"
1313
"github.com/mengdj/goctl-rest-client/conf"
1414
"github.com/pkg/errors"
15+
"github.com/zeromicro/go-zero/core/breaker"
1516
"github.com/zeromicro/go-zero/core/mapping"
1617
"github.com/zeromicro/go-zero/rest/httpc"
18+
"go.opentelemetry.io/otel"
19+
"go.opentelemetry.io/otel/codes"
20+
"go.opentelemetry.io/otel/propagation"
21+
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
22+
oteltrace "go.opentelemetry.io/otel/trace"
1723
"net/http"
1824
nurl "net/url"
1925
"time"
@@ -22,6 +28,8 @@ import (
2228
type (
2329
restResty struct {
2430
client *resty.Client
31+
name string
32+
trace bool
2533
}
2634
)
2735

@@ -32,6 +40,8 @@ const (
3240
jsonKey = "json"
3341
slash = "/"
3442
colon = ':'
43+
44+
traceName = "gozero-rest-client"
3545
)
3646

3747
var (
@@ -44,50 +54,73 @@ func (rds *restResty) Do(ctx context.Context, method, url string, data interface
4454
payload, _ = data.(*RestPayload)
4555
rertyR = rds.client.R().SetContext(ctx)
4656
rertyP *resty.Response
47-
err error
57+
err, errx error
4858
purl *nurl.URL
4959
val map[string]map[string]interface{}
60+
span oteltrace.Span
5061
)
5162
if purl, err = nurl.Parse(url); err != nil {
52-
//parse url
5363
return nil, err
5464
}
5565
if payload.Request != nil {
56-
//parse request
5766
if val, err = mapping.Marshal(payload.Request); err != nil {
5867
return nil, err
5968
}
60-
//path
6169
if pv, ok := val[pathKey]; ok {
6270
if err = fillPath(purl, pv); err != nil {
6371
return nil, err
6472
}
6573
}
66-
//form
6774
if fv := buildFormQuery(purl, val[formKey]); len(fv) > 0 {
6875
rertyR.SetFormDataFromValues(fv)
6976
}
70-
//body
7177
if jv, ok := val[jsonKey]; ok {
7278
if method == http.MethodGet {
7379
return nil, ErrGetWithBody
7480
}
7581
rertyR.SetBody(jv)
7682
rertyR.SetHeader(ContentType, JsonContentType)
7783
}
78-
//header
7984
if hv, ok := val[headerKey]; ok {
8085
for k, v := range hv {
8186
rertyR.SetHeader(k, fmt.Sprint(v))
8287
}
8388
}
84-
//result
8589
if nil != payload.Response {
8690
rertyR.SetResult(payload.Response)
8791
}
8892
}
89-
if rertyP, err = rertyR.Execute(method, purl.String()); nil != err {
90-
return nil, err
93+
if rds.trace {
94+
//链路跟踪
95+
ctx, span = otel.Tracer(traceName).Start(
96+
ctx,
97+
url,
98+
oteltrace.WithSpanKind(oteltrace.SpanKindClient),
99+
)
100+
defer span.End()
101+
otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(rertyR.Header))
102+
}
103+
//熔断
104+
if errx = breaker.GetBreaker(rds.name).DoWithAcceptable(func() error {
105+
if rertyP, err = rertyR.Execute(method, purl.String()); nil != err {
106+
return err
107+
}
108+
return nil
109+
}, func(err error) bool {
110+
if nil != err {
111+
return false
112+
}
113+
return rertyP.StatusCode() < http.StatusInternalServerError
114+
}); nil != errx {
115+
if rds.trace {
116+
span.RecordError(errx)
117+
span.SetStatus(codes.Error, errx.Error())
118+
}
119+
return nil, errx
120+
}
121+
if rds.trace {
122+
span.SetAttributes(semconv.HTTPAttributesFromHTTPStatusCode(rertyP.StatusCode())...)
123+
span.SetStatus(semconv.SpanStatusFromHTTPStatusCodeAndSpanKind(rertyP.StatusCode(), oteltrace.SpanKindClient))
91124
}
92125
return rertyP.RawResponse, nil
93126
}
@@ -96,19 +129,63 @@ func (rds *restResty) DoRequest(r *http.Request) (*http.Response, error) {
96129
return nil, NotSupport
97130
}
98131

99-
func NewRestResty(cnf conf.TransferConf, opts ...RestOption) httpc.Service {
100-
client := resty.New().SetDebug(cnf.Rety.Debug).SetAllowGetMethodPayload(cnf.Rety.AllowGetMethodPayload)
132+
func NewRestResty(name string, cnf conf.TransferConf, opts ...RestOption) httpc.Service {
133+
r := &restResty{
134+
client: resty.New().SetDebug(cnf.Resty.Debug).SetAllowGetMethodPayload(cnf.Resty.AllowGetMethodPayload),
135+
name: name,
136+
}
101137
//init
102-
if cnf.Rety.Token != "" {
103-
client.SetAuthToken(cnf.Rety.Token)
138+
if cnf.Resty.Token != "" {
139+
r.client.SetAuthToken(cnf.Resty.Token)
140+
}
141+
if cnf.Resty.Timeout != 0 {
142+
r.client.SetTimeout(time.Duration(cnf.Resty.Timeout))
143+
}
144+
if len(cnf.Resty.Header) > 0 {
145+
r.client.SetHeaders(cnf.Resty.Header)
146+
}
147+
for _, opt := range opts {
148+
opt(r)
149+
}
150+
return r
151+
}
152+
153+
func WithRestyErrorHook(hook resty.ErrorHook) RestOption {
154+
return func(v interface{}) {
155+
if target, ok := v.(*restResty); ok {
156+
target.client.OnError(hook)
157+
}
104158
}
105-
if cnf.Rety.Timeout != 0 {
106-
client.SetTimeout(time.Duration(cnf.Rety.Timeout))
159+
}
160+
161+
func WithRestyBeforeRequest(req resty.RequestMiddleware) RestOption {
162+
return func(v interface{}) {
163+
if target, ok := v.(*restResty); ok {
164+
target.client.OnBeforeRequest(req)
165+
}
166+
}
167+
}
168+
169+
func WithDisableWarn(dis bool) RestOption {
170+
return func(v interface{}) {
171+
if target, ok := v.(*restResty); ok {
172+
target.client.SetDisableWarn(dis)
173+
}
107174
}
108-
if len(cnf.Rety.Header) > 0 {
109-
client.SetHeaders(cnf.Rety.Header)
175+
}
176+
177+
func WithTrace(trace bool) RestOption {
178+
return func(v interface{}) {
179+
if target, ok := v.(*restResty); ok {
180+
target.trace = trace
181+
}
110182
}
111-
return &restResty{
112-
client: client,
183+
}
184+
185+
func WithRestyAfterResponse(resp resty.ResponseMiddleware) RestOption {
186+
return func(v interface{}) {
187+
if target, ok := v.(*restResty); ok {
188+
target.client.OnAfterResponse(resp)
189+
}
113190
}
114191
}

go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ require (
1111
github.com/zeromicro/go-zero v1.4.4
1212
github.com/zeromicro/go-zero/tools/goctl v1.4.4
1313
github.com/zeromicro/zero-contrib/zrpc/registry/consul v0.0.0-20230212061721-86dbe4a9e613
14+
go.opentelemetry.io/otel v1.10.0
15+
go.opentelemetry.io/otel/trace v1.10.0
1416
golang.org/x/mod v0.7.0
1517
)

go.sum

+3
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,7 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
810810
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
811811
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
812812
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
813+
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
813814
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
814815
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
815816
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -923,6 +924,7 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5
923924
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
924925
github.com/rabbitmq/amqp091-go v1.1.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0VTJ0kHRghqbM=
925926
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
927+
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
926928
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
927929
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
928930
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -1687,6 +1689,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
16871689
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
16881690
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
16891691
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
1692+
gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk=
16901693
gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
16911694
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
16921695
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=

0 commit comments

Comments
 (0)