diff --git a/go.mod b/go.mod index 4c8ccb9..aa7a15f 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,7 @@ module go.unistack.org/micro-client-http/v4 go 1.22.0 -toolchain go1.23.3 - -require go.unistack.org/micro/v4 v4.1.1 +require go.unistack.org/micro/v4 v4.1.2 require ( github.com/ash3in/uuidv8 v1.2.0 // indirect diff --git a/go.sum b/go.sum index f7adb81..c7c5c14 100644 --- a/go.sum +++ b/go.sum @@ -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= 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/v4 v4.1.1 h1:Cx2Uo5LN3J3lIxLv2jNYSqoVQbGShwMQgr4cffjqqVI= -go.unistack.org/micro/v4 v4.1.1/go.mod h1:lr3oYED8Ay1vjK68QqRw30QOtdk/ffpZqMFDasOUhKw= +go.unistack.org/micro/v4 v4.1.2 h1:9SOlPYyPNNFpg1A7BsvhDyQm3gysLH1AhWbDCp1hyoY= +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/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= diff --git a/http.go b/http.go index 42c9b45..d2952ca 100644 --- a/http.go +++ b/http.go @@ -115,7 +115,7 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client. u, err = u.Parse(path) if err != nil { - return nil, errors.BadRequest("go.micro.client", err.Error()) + return nil, errors.BadRequest("go.micro.client", "%+v", err) } var nmsg interface{} @@ -126,12 +126,12 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client. } 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)) 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 @@ -174,11 +174,11 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client. for k, required := range vm { v, err = rutil.StructFieldByPath(msg, k) 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 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 } @@ -194,7 +194,7 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client. b, err := cf.Marshal(nmsg) 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 @@ -207,7 +207,7 @@ func newRequest(ctx context.Context, log logger.Logger, addr string, req client. } if err != nil { - return nil, errors.BadRequest("go.micro.client", err.Error()) + return nil, errors.BadRequest("go.micro.client", "%+v", err) } hreq.Header = header @@ -230,7 +230,7 @@ func (h *httpClient) call(ctx context.Context, addr string, req client.Request, cf, err := h.newCodec(ct) 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) if err != nil { @@ -243,14 +243,14 @@ func (h *httpClient) call(ctx context.Context, addr string, req client.Request, switch err := err.(type) { case *url.Error: 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: 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() @@ -267,12 +267,12 @@ func (h *httpClient) stream(ctx context.Context, addr string, req client.Request // get codec cf, err := h.newCodec(ct) 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) 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{ @@ -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 t, err := callOpts.Backoff(ctx, req, i) 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 @@ -410,7 +410,7 @@ func (h *httpClient) Call(ctx context.Context, req client.Request, rsp interface // TODO apply any filtering here routes, err = h.opts.Lookup(ctx, req, callOpts) if err != nil { - return errors.InternalServerError("go.micro.client", err.Error()) + return errors.InternalServerError("go.micro.client", "%+v", err) } // 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 t, cerr := callOpts.Backoff(ctx, req, i) 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 @@ -546,7 +546,7 @@ func (h *httpClient) Stream(ctx context.Context, req client.Request, opts ...cli // TODO apply any filtering here routes, err = h.opts.Lookup(ctx, req, callOpts) 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 diff --git a/options.go b/options.go index 20b220e..5772a21 100644 --- a/options.go +++ b/options.go @@ -1,11 +1,12 @@ package http import ( + "context" "net" "net/http" + "go.unistack.org/micro/v4/client" "go.unistack.org/micro/v4/metadata" - "go.unistack.org/micro/v4/options" ) var ( @@ -26,73 +27,171 @@ var ( DefaultMaxSendMsgSize = 1024 * 1024 * 4 ) +type poolMaxStreams struct{} + // PoolMaxStreams maximum streams on a connectioin -func PoolMaxStreams(n int) options.Option { - return options.NewOption("PoolMaxStreams")(n) +func PoolMaxStreams(n int) client.Option { + 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 -func PoolMaxIdle(n int) options.Option { - return options.NewOption("PoolMaxIdle")(n) +func PoolMaxIdle(d int) client.Option { + 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. -func MaxRecvMsgSize(n int) options.Option { - return options.NewOption("MaxRecvMsgSize")(n) +func MaxRecvMsgSize(s int) client.Option { + 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. -func MaxSendMsgSize(n int) options.Option { - return options.NewOption("MaxSendMsgSize")(n) +func MaxSendMsgSize(s int) client.Option { + 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 // HTTPClient pass http.Client option to client Call -func HTTPClient(c *http.Client) options.Option { - return options.NewOption("HTTPClient")(c) +func HTTPClient(c *http.Client) client.Option { + 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 // HTTPDialer pass net.Dialer option to client -func HTTPDialer(d *net.Dialer) options.Option { - return options.NewOption("HTTPDialer")(d) +func HTTPDialer(d *net.Dialer) client.Option { + 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 -func Method(m string) options.Option { - return options.NewOption("Method")(m) +func Method(m string) client.CallOption { + 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 -func Path(p string) options.Option { - return options.NewOption("Path")(p) +func Path(p string) client.Option { + 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 -func Body(b string) options.Option { - return options.NewOption("Body")(b) +func Body(b string) client.Option { + 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 { - return options.NewOption("ErrorMap")(m) +type errorMapKey struct{} + +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 -func StructTags(tags []string) options.Option { - return options.NewOption("StructTags")(tags) +func StructTags(tags []string) client.Option { + 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 -func Metadata(md metadata.Metadata) options.Option { - return options.NewOption("Metadata")(md) +func Metadata(md metadata.Metadata) client.Option { + 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 -func Cookie(cookies ...string) options.Option { - return options.NewOption("Cookie")(cookies) +func Cookie(cookies ...string) client.Option { + 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 -func Header(headers ...string) options.Option { - return options.NewOption("Header")(headers) +func Header(headers ...string) client.Option { + return func(o *client.Options) { + if o.Context == nil { + o.Context = context.Background() + } + o.Context = context.WithValue(o.Context, headerKey{}, headers) + } } diff --git a/stream.go b/stream.go index 2a69b89..9f30103 100644 --- a/stream.go +++ b/stream.go @@ -90,7 +90,7 @@ func (h *httpStream) Recv(msg interface{}) error { hrsp, err := http.ReadResponse(h.reader, new(http.Request)) if err != nil { - return errors.InternalServerError("go.micro.client", err.Error()) + return errors.InternalServerError("go.micro.client", "%+v", err) } 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) { 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 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 } @@ -163,7 +163,7 @@ func (h *httpStream) parseRsp(ctx context.Context, log logger.Logger, hrsp *http } 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 { diff --git a/util.go b/util.go index b0496c5..d463185 100644 --- a/util.go +++ b/util.go @@ -284,7 +284,7 @@ func (h *httpClient) parseRsp(ctx context.Context, hrsp *http.Response, rsp inte if h.opts.Logger.V(logger.ErrorLevel) { 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) { 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) { @@ -303,7 +303,7 @@ func (h *httpClient) parseRsp(ctx context.Context, hrsp *http.Response, rsp inte // succeseful response if hrsp.StatusCode < 400 { 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 } @@ -323,7 +323,7 @@ func (h *httpClient) parseRsp(ctx context.Context, hrsp *http.Response, rsp inte } 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 {