Add wrapper implementation
This commit is contained in:
		| @@ -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) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user