Add wrapper implementation
This commit is contained in:
parent
4fa909a3c7
commit
fb172df0ce
@ -12,6 +12,7 @@ type options struct {
|
||||
broker broker.Broker
|
||||
registry registry.Registry
|
||||
transport transport.Transport
|
||||
wrappers []Wrapper
|
||||
}
|
||||
|
||||
// Broker to be used for pub/sub
|
||||
@ -48,3 +49,10 @@ func Transport(t transport.Transport) Option {
|
||||
o.transport = t
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a Wrapper to a list of options passed into the client
|
||||
func Wrap(w Wrapper) Option {
|
||||
return func(o *options) {
|
||||
o.wrappers = append(o.wrappers, w)
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,8 @@ type rpcClient struct {
|
||||
}
|
||||
|
||||
func newRpcClient(opt ...Option) Client {
|
||||
var once sync.Once
|
||||
|
||||
opts := options{
|
||||
codecs: make(map[string]CodecFunc),
|
||||
}
|
||||
@ -43,12 +45,19 @@ func newRpcClient(opt ...Option) Client {
|
||||
opts.broker = broker.DefaultBroker
|
||||
}
|
||||
|
||||
var once sync.Once
|
||||
|
||||
return &rpcClient{
|
||||
rc := &rpcClient{
|
||||
once: once,
|
||||
opts: opts,
|
||||
}
|
||||
|
||||
c := Client(rc)
|
||||
|
||||
// wrap in reverse
|
||||
for i := len(opts.wrappers); i > 0; i-- {
|
||||
c = opts.wrappers[i-1](c)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (r *rpcClient) codecFunc(contentType string) (codecFunc, error) {
|
||||
|
37
client/wrapper.go
Normal file
37
client/wrapper.go
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Wrapper is a type of middleware for the go-micro client. It allows
|
||||
the client to be "wrapped" so that requests and responses can be intercepted
|
||||
to perform extra requirements such as auth, tracing, monitoring, logging, etc.
|
||||
|
||||
Example usage:
|
||||
|
||||
import (
|
||||
"log"
|
||||
"github.com/micro/go-micro/client"
|
||||
|
||||
)
|
||||
|
||||
type LogWrapper struct {
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (l *LogWrapper) Call(ctx context.Context, req Request, rsp interface{}) error {
|
||||
log.Println("Making request to service " + req.Service() + " method " + req.Method())
|
||||
return w.Client.Call(ctx, req, rsp)
|
||||
}
|
||||
|
||||
func Wrapper(c client.Client) client.Client {
|
||||
return &LogWrapper{c}
|
||||
}
|
||||
|
||||
func main() {
|
||||
c := client.NewClient(client.Wrap(Wrapper))
|
||||
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
package client
|
||||
|
||||
// Wrapper wraps a client and returns a client
|
||||
type Wrapper func(Client) Client
|
87
examples/client/wrapper.go
Normal file
87
examples/client/wrapper.go
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
An example of how to use client.Wrapper as middleware
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/cmd"
|
||||
c "github.com/micro/go-micro/context"
|
||||
example "github.com/micro/go-micro/examples/server/proto/example"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// log wrapper logs every time a request is made
|
||||
type logWrapper struct {
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (l *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}) error {
|
||||
md, _ := c.GetMetadata(ctx)
|
||||
fmt.Printf("[Log Wrapper] ctx: %v service: %s method: %s\n", md, req.Service(), req.Method())
|
||||
return l.Client.Call(ctx, req, rsp)
|
||||
}
|
||||
|
||||
// trace wrapper attaches a unique trace ID - timestamp
|
||||
type traceWrapper struct {
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (t *traceWrapper) Call(ctx context.Context, req client.Request, rsp interface{}) error {
|
||||
ctx = c.WithMetadata(ctx, map[string]string{
|
||||
"X-Trace-Id": fmt.Sprintf("%d", time.Now().Unix()),
|
||||
})
|
||||
return t.Client.Call(ctx, req, rsp)
|
||||
}
|
||||
|
||||
// Implements client.Wrapper as logWrapper
|
||||
func logWrap(c client.Client) client.Client {
|
||||
return &logWrapper{c}
|
||||
}
|
||||
|
||||
// Implements client.Wrapper as traceWrapper
|
||||
func traceWrap(c client.Client) client.Client {
|
||||
return &traceWrapper{c}
|
||||
}
|
||||
|
||||
// Calls the example service
|
||||
func call(i int) {
|
||||
// Create new request to service go.micro.srv.example, method Example.Call
|
||||
req := client.NewRequest("go.micro.srv.example", "Example.Call", &example.Request{
|
||||
Name: "John",
|
||||
})
|
||||
|
||||
// create context with metadata
|
||||
ctx := c.WithMetadata(context.Background(), map[string]string{
|
||||
"X-User-Id": "john",
|
||||
"X-From-Id": "script",
|
||||
})
|
||||
|
||||
rsp := &example.Response{}
|
||||
|
||||
// Call service
|
||||
if err := client.Call(ctx, req, rsp); err != nil {
|
||||
fmt.Println("call err: ", err, rsp)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Init()
|
||||
|
||||
// Wrap the default client
|
||||
client.DefaultClient = logWrap(client.DefaultClient)
|
||||
|
||||
call(0)
|
||||
|
||||
// Wrap using client.Wrap option
|
||||
client.DefaultClient = client.NewClient(
|
||||
client.Wrap(traceWrap),
|
||||
client.Wrap(logWrap),
|
||||
)
|
||||
|
||||
call(1)
|
||||
}
|
Loading…
Reference in New Issue
Block a user