revert and update options && fix linter
All checks were successful
lint / lint (pull_request) Successful in 1m49s
test / test (pull_request) Successful in 3m18s

This commit is contained in:
2025-02-25 13:03:57 +03:00
parent 334a10e26d
commit f351a9129d
6 changed files with 156 additions and 59 deletions

4
go.mod
View File

@@ -2,9 +2,7 @@ module go.unistack.org/micro-client-http/v4
go 1.22.0 go 1.22.0
toolchain go1.23.3 require go.unistack.org/micro/v4 v4.1.2
require go.unistack.org/micro/v4 v4.1.1
require ( require (
github.com/ash3in/uuidv8 v1.2.0 // indirect github.com/ash3in/uuidv8 v1.2.0 // indirect

4
go.sum
View File

@@ -22,8 +22,8 @@ github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
go.unistack.org/micro-proto/v4 v4.1.0 h1:qPwL2n/oqh9RE3RTTDgt28XK3QzV597VugQPaw9lKUk= go.unistack.org/micro-proto/v4 v4.1.0 h1:qPwL2n/oqh9RE3RTTDgt28XK3QzV597VugQPaw9lKUk=
go.unistack.org/micro-proto/v4 v4.1.0/go.mod h1:ArmK7o+uFvxSY3dbJhKBBX4Pm1rhWdLEFf3LxBrMtec= go.unistack.org/micro-proto/v4 v4.1.0/go.mod h1:ArmK7o+uFvxSY3dbJhKBBX4Pm1rhWdLEFf3LxBrMtec=
go.unistack.org/micro/v4 v4.1.1 h1:Cx2Uo5LN3J3lIxLv2jNYSqoVQbGShwMQgr4cffjqqVI= go.unistack.org/micro/v4 v4.1.2 h1:9SOlPYyPNNFpg1A7BsvhDyQm3gysLH1AhWbDCp1hyoY=
go.unistack.org/micro/v4 v4.1.1/go.mod h1:lr3oYED8Ay1vjK68QqRw30QOtdk/ffpZqMFDasOUhKw= go.unistack.org/micro/v4 v4.1.2/go.mod h1:lr3oYED8Ay1vjK68QqRw30QOtdk/ffpZqMFDasOUhKw=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=

34
http.go
View File

@@ -115,7 +115,7 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client.
u, err = u.Parse(path) u, err = u.Parse(path)
if err != nil { if err != nil {
return nil, errors.BadRequest("go.micro.client", err.Error()) return nil, errors.BadRequest("go.micro.client", "%+v", err)
} }
var nmsg interface{} var nmsg interface{}
@@ -126,12 +126,12 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client.
} }
if err != nil { if err != nil {
return nil, errors.BadRequest("go.micro.client", err.Error()) return nil, errors.BadRequest("go.micro.client", "%+v", err)
} }
u, err = url.Parse(fmt.Sprintf("%s://%s%s", scheme, host, path)) u, err = url.Parse(fmt.Sprintf("%s://%s%s", scheme, host, path))
if err != nil { if err != nil {
return nil, errors.BadRequest("go.micro.client", err.Error()) return nil, errors.BadRequest("go.micro.client", "%+v", err)
} }
var cookies []*http.Cookie var cookies []*http.Cookie
@@ -174,11 +174,11 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client.
for k, required := range vm { for k, required := range vm {
v, err = rutil.StructFieldByPath(msg, k) v, err = rutil.StructFieldByPath(msg, k)
if err != nil { if err != nil {
return nil, errors.BadRequest("go.micro.client", err.Error()) return nil, errors.BadRequest("go.micro.client", "%+v", err)
} }
if rutil.IsZero(v) { if rutil.IsZero(v) {
if required == "true" { if required == "true" {
return nil, errors.BadRequest("go.micro.client", fmt.Sprintf("required field %s not set", k)) return nil, errors.BadRequest("go.micro.client", "required field %s not set", k)
} }
continue continue
} }
@@ -194,7 +194,7 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client.
b, err := cf.Marshal(nmsg) b, err := cf.Marshal(nmsg)
if err != nil { if err != nil {
return nil, errors.BadRequest("go.micro.client", err.Error()) return nil, errors.BadRequest("go.micro.client", "%+v", err)
} }
var hreq *http.Request var hreq *http.Request
@@ -207,7 +207,7 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client.
} }
if err != nil { if err != nil {
return nil, errors.BadRequest("go.micro.client", err.Error()) return nil, errors.BadRequest("go.micro.client", "%+v", err)
} }
hreq.Header = header hreq.Header = header
@@ -230,7 +230,7 @@ func (h *httpClient) call(ctx context.Context, addr string, req client.Request,
cf, err := h.newCodec(ct) cf, err := h.newCodec(ct)
if err != nil { if err != nil {
return errors.BadRequest("go.micro.client", err.Error()) return errors.BadRequest("go.micro.client", "%+v", err)
} }
hreq, err := newRequest(ctx, h.opts.Logger, addr, req, ct, cf, req.Body(), opts) hreq, err := newRequest(ctx, h.opts.Logger, addr, req, ct, cf, req.Body(), opts)
if err != nil { if err != nil {
@@ -243,14 +243,14 @@ func (h *httpClient) call(ctx context.Context, addr string, req client.Request,
switch err := err.(type) { switch err := err.(type) {
case *url.Error: case *url.Error:
if err, ok := err.Err.(net.Error); ok && err.Timeout() { if err, ok := err.Err.(net.Error); ok && err.Timeout() {
return errors.Timeout("go.micro.client", err.Error()) return errors.Timeout("go.micro.client", "%+v", err)
} }
case net.Error: case net.Error:
if err.Timeout() { if err.Timeout() {
return errors.Timeout("go.micro.client", err.Error()) return errors.Timeout("go.micro.client", "%+v", err)
} }
} }
return errors.InternalServerError("go.micro.client", err.Error()) return errors.InternalServerError("go.micro.client", "%+v", err)
} }
defer hrsp.Body.Close() defer hrsp.Body.Close()
@@ -267,12 +267,12 @@ func (h *httpClient) stream(ctx context.Context, addr string, req client.Request
// get codec // get codec
cf, err := h.newCodec(ct) cf, err := h.newCodec(ct)
if err != nil { if err != nil {
return nil, errors.BadRequest("go.micro.client", err.Error()) return nil, errors.BadRequest("go.micro.client", "%+v", err)
} }
cc, err := (h.httpcli.Transport).(*http.Transport).DialContext(ctx, "tcp", addr) cc, err := (h.httpcli.Transport).(*http.Transport).DialContext(ctx, "tcp", addr)
if err != nil { if err != nil {
return nil, errors.InternalServerError("go.micro.client", fmt.Sprintf("Error dialing: %v", err)) return nil, errors.InternalServerError("go.micro.client", "Error dialing: %v", err)
} }
return &httpStream{ return &httpStream{
@@ -396,7 +396,7 @@ func (h *httpClient) Call(ctx context.Context, req client.Request, rsp interface
// call backoff first. Someone may want an initial start delay // call backoff first. Someone may want an initial start delay
t, err := callOpts.Backoff(ctx, req, i) t, err := callOpts.Backoff(ctx, req, i)
if err != nil { if err != nil {
return errors.InternalServerError("go.micro.client", err.Error()) return errors.InternalServerError("go.micro.client", "%+v", err)
} }
// only sleep if greater than 0 // only sleep if greater than 0
@@ -410,7 +410,7 @@ func (h *httpClient) Call(ctx context.Context, req client.Request, rsp interface
// TODO apply any filtering here // TODO apply any filtering here
routes, err = h.opts.Lookup(ctx, req, callOpts) routes, err = h.opts.Lookup(ctx, req, callOpts)
if err != nil { if err != nil {
return errors.InternalServerError("go.micro.client", err.Error()) return errors.InternalServerError("go.micro.client", "%+v", err)
} }
// balance the list of nodes // balance the list of nodes
@@ -532,7 +532,7 @@ func (h *httpClient) Stream(ctx context.Context, req client.Request, opts ...cli
// call backoff first. Someone may want an initial start delay // call backoff first. Someone may want an initial start delay
t, cerr := callOpts.Backoff(ctx, req, i) t, cerr := callOpts.Backoff(ctx, req, i)
if cerr != nil { if cerr != nil {
return nil, errors.InternalServerError("go.micro.client", cerr.Error()) return nil, errors.InternalServerError("go.micro.client", "%+v", cerr)
} }
// only sleep if greater than 0 // only sleep if greater than 0
@@ -546,7 +546,7 @@ func (h *httpClient) Stream(ctx context.Context, req client.Request, opts ...cli
// TODO apply any filtering here // TODO apply any filtering here
routes, err = h.opts.Lookup(ctx, req, callOpts) routes, err = h.opts.Lookup(ctx, req, callOpts)
if err != nil { if err != nil {
return nil, errors.InternalServerError("go.micro.client", err.Error()) return nil, errors.InternalServerError("go.micro.client", "%+v", err)
} }
// balance the list of nodes // balance the list of nodes

View File

@@ -1,11 +1,12 @@
package http package http
import ( import (
"context"
"net" "net"
"net/http" "net/http"
"go.unistack.org/micro/v4/client"
"go.unistack.org/micro/v4/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v4/options"
) )
var ( var (
@@ -26,73 +27,171 @@ var (
DefaultMaxSendMsgSize = 1024 * 1024 * 4 DefaultMaxSendMsgSize = 1024 * 1024 * 4
) )
type poolMaxStreams struct{}
// PoolMaxStreams maximum streams on a connectioin // PoolMaxStreams maximum streams on a connectioin
func PoolMaxStreams(n int) options.Option { func PoolMaxStreams(n int) client.Option {
return options.NewOption("PoolMaxStreams")(n) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, poolMaxStreams{}, n)
}
}
type poolMaxIdle struct{}
// PoolMaxIdle maximum idle conns of a pool // PoolMaxIdle maximum idle conns of a pool
func PoolMaxIdle(n int) options.Option { func PoolMaxIdle(d int) client.Option {
return options.NewOption("PoolMaxIdle")(n) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, poolMaxIdle{}, d)
}
}
type maxRecvMsgSizeKey struct{}
// MaxRecvMsgSize set the maximum size of message that client can receive. // MaxRecvMsgSize set the maximum size of message that client can receive.
func MaxRecvMsgSize(n int) options.Option { func MaxRecvMsgSize(s int) client.Option {
return options.NewOption("MaxRecvMsgSize")(n) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
}
o.Context = context.WithValue(o.Context, maxRecvMsgSizeKey{}, s)
}
} }
type maxSendMsgSizeKey struct{}
// MaxSendMsgSize set the maximum size of message that client can send. // MaxSendMsgSize set the maximum size of message that client can send.
func MaxSendMsgSize(n int) options.Option { func MaxSendMsgSize(s int) client.Option {
return options.NewOption("MaxSendMsgSize")(n) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, maxSendMsgSizeKey{}, s)
}
}
type httpClientKey struct{}
// nolint: golint // nolint: golint
// HTTPClient pass http.Client option to client Call // HTTPClient pass http.Client option to client Call
func HTTPClient(c *http.Client) options.Option { func HTTPClient(c *http.Client) client.Option {
return options.NewOption("HTTPClient")(c) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, httpClientKey{}, c)
}
}
type httpDialerKey struct{}
// nolint: golint // nolint: golint
// HTTPDialer pass net.Dialer option to client // HTTPDialer pass net.Dialer option to client
func HTTPDialer(d *net.Dialer) options.Option { func HTTPDialer(d *net.Dialer) client.Option {
return options.NewOption("HTTPDialer")(d) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, httpDialerKey{}, d)
}
}
type methodKey struct{}
// Method pass method option to client Call // Method pass method option to client Call
func Method(m string) options.Option { func Method(m string) client.CallOption {
return options.NewOption("Method")(m) return func(o *client.CallOptions) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, methodKey{}, m)
}
}
type pathKey struct{}
// Path spcecifies path option to client Call // Path spcecifies path option to client Call
func Path(p string) options.Option { func Path(p string) client.Option {
return options.NewOption("Path")(p) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, pathKey{}, p)
}
}
type bodyKey struct{}
// Body specifies body option to client Call // Body specifies body option to client Call
func Body(b string) options.Option { func Body(b string) client.Option {
return options.NewOption("Body")(b) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
}
o.Context = context.WithValue(o.Context, bodyKey{}, b)
}
} }
func ErrorMap(m map[string]interface{}) options.Option { type errorMapKey struct{}
return options.NewOption("ErrorMap")(m)
func ErrorMap(m map[string]interface{}) client.Option {
return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, errorMapKey{}, m)
}
}
type structTagsKey struct{}
// StructTags pass tags slice option to client Call // StructTags pass tags slice option to client Call
func StructTags(tags []string) options.Option { func StructTags(tags []string) client.Option {
return options.NewOption("StructTags")(tags) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, structTagsKey{}, tags)
}
}
type metadataKey struct{}
// Metadata pass metadata to client Call // Metadata pass metadata to client Call
func Metadata(md metadata.Metadata) options.Option { func Metadata(md metadata.Metadata) client.Option {
return options.NewOption("Metadata")(md) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
} }
o.Context = context.WithValue(o.Context, metadataKey{}, md)
}
}
type cookieKey struct{}
// Cookie pass cookie to client Call // Cookie pass cookie to client Call
func Cookie(cookies ...string) options.Option { func Cookie(cookies ...string) client.Option {
return options.NewOption("Cookie")(cookies) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
}
o.Context = context.WithValue(o.Context, cookieKey{}, cookies)
}
} }
type headerKey struct{}
// Header pass cookie to client Call // Header pass cookie to client Call
func Header(headers ...string) options.Option { func Header(headers ...string) client.Option {
return options.NewOption("Header")(headers) return func(o *client.Options) {
if o.Context == nil {
o.Context = context.Background()
}
o.Context = context.WithValue(o.Context, headerKey{}, headers)
}
} }

View File

@@ -90,7 +90,7 @@ func (h *httpStream) Recv(msg interface{}) error {
hrsp, err := http.ReadResponse(h.reader, new(http.Request)) hrsp, err := http.ReadResponse(h.reader, new(http.Request))
if err != nil { if err != nil {
return errors.InternalServerError("go.micro.client", err.Error()) return errors.InternalServerError("go.micro.client", "%+v", err)
} }
defer hrsp.Body.Close() defer hrsp.Body.Close()
@@ -136,7 +136,7 @@ func (h *httpStream) parseRsp(ctx context.Context, log logger.Logger, hrsp *http
if log.V(logger.ErrorLevel) { if log.V(logger.ErrorLevel) {
log.Error(ctx, "failed to read body", err) log.Error(ctx, "failed to read body", err)
} }
return errors.InternalServerError("go.micro.client", string(buf)) return errors.InternalServerError("go.micro.client", "%s", buf)
} }
} }
@@ -146,7 +146,7 @@ func (h *httpStream) parseRsp(ctx context.Context, log logger.Logger, hrsp *http
if hrsp.StatusCode < 400 { if hrsp.StatusCode < 400 {
if err = cf.Unmarshal(buf, rsp); err != nil { if err = cf.Unmarshal(buf, rsp); err != nil {
return errors.InternalServerError("go.micro.client", err.Error()) return errors.InternalServerError("go.micro.client", "%+v", err)
} }
return nil return nil
} }
@@ -163,7 +163,7 @@ func (h *httpStream) parseRsp(ctx context.Context, log logger.Logger, hrsp *http
} }
if cerr := cf.Unmarshal(buf, rerr); cerr != nil { if cerr := cf.Unmarshal(buf, rerr); cerr != nil {
return errors.InternalServerError("go.micro.client", cerr.Error()) return errors.InternalServerError("go.micro.client", "%+v", cerr)
} }
if err, ok = rerr.(error); !ok { if err, ok = rerr.(error); !ok {

View File

@@ -284,7 +284,7 @@ func (h *httpClient) parseRsp(ctx context.Context, hrsp *http.Response, rsp inte
if h.opts.Logger.V(logger.ErrorLevel) { if h.opts.Logger.V(logger.ErrorLevel) {
h.opts.Logger.Error(ctx, "failed to read body", err) h.opts.Logger.Error(ctx, "failed to read body", err)
} }
return errors.InternalServerError("go.micro.client", string(buf)) return errors.InternalServerError("go.micro.client", "%s", buf)
} }
} }
@@ -293,7 +293,7 @@ func (h *httpClient) parseRsp(ctx context.Context, hrsp *http.Response, rsp inte
if h.opts.Logger.V(logger.DebugLevel) { if h.opts.Logger.V(logger.DebugLevel) {
h.opts.Logger.Debug(ctx, fmt.Sprintf("response with %v unknown content-type %s %s", hrsp.Header, ct, buf)) h.opts.Logger.Debug(ctx, fmt.Sprintf("response with %v unknown content-type %s %s", hrsp.Header, ct, buf))
} }
return errors.InternalServerError("go.micro.client", cerr.Error()) return errors.InternalServerError("go.micro.client", "%+v", cerr)
} }
if h.opts.Logger.V(logger.DebugLevel) { if h.opts.Logger.V(logger.DebugLevel) {
@@ -303,7 +303,7 @@ func (h *httpClient) parseRsp(ctx context.Context, hrsp *http.Response, rsp inte
// succeseful response // succeseful response
if hrsp.StatusCode < 400 { if hrsp.StatusCode < 400 {
if err = cf.Unmarshal(buf, rsp); err != nil { if err = cf.Unmarshal(buf, rsp); err != nil {
return errors.InternalServerError("go.micro.client", err.Error()) return errors.InternalServerError("go.micro.client", "%+v", err)
} }
return nil return nil
} }
@@ -323,7 +323,7 @@ func (h *httpClient) parseRsp(ctx context.Context, hrsp *http.Response, rsp inte
} }
if cerr := cf.Unmarshal(buf, rerr); cerr != nil { if cerr := cf.Unmarshal(buf, rerr); cerr != nil {
return errors.InternalServerError("go.micro.client", cerr.Error()) return errors.InternalServerError("go.micro.client", "%+v", cerr)
} }
if err, ok = rerr.(error); !ok { if err, ok = rerr.(error); !ok {