# Wrappers Wrappers are a form of middleware that can be used with go-micro services. They can wrap both the Client and Server handlers. ## Client Interface ```go // Wrapper wraps a client and returns a client type Wrapper func(Client) Client // StreamWrapper wraps a Stream and returns the equivalent type StreamWrapper func(Streamer) Streamer ``` ## Handler Interface ```go // HandlerFunc represents a single method of a handler. It's used primarily // for the wrappers. What's handed to the actual method is the concrete // request and response types. type HandlerFunc func(ctx context.Context, req Request, rsp interface{}) error // SubscriberFunc represents a single method of a subscriber. It's used primarily // for the wrappers. What's handed to the actual method is the concrete // publication message. type SubscriberFunc func(ctx context.Context, msg Event) error // HandlerWrapper wraps the HandlerFunc and returns the equivalent type HandlerWrapper func(HandlerFunc) HandlerFunc // SubscriberWrapper wraps the SubscriberFunc and returns the equivalent type SubscriberWrapper func(SubscriberFunc) SubscriberFunc // StreamerWrapper wraps a Streamer interface and returns the equivalent. // Because streams exist for the lifetime of a method invocation this // is a convenient way to wrap a Stream as its in use for trace, monitoring, // metrics, etc. type StreamerWrapper func(Streamer) Streamer ``` ## Client Wrapper Usage Here's a basic log wrapper for the client ```go type logWrapper struct { client.Client } func (l *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error { md, _ := metadata.FromContext(ctx) fmt.Printf("[Log Wrapper] ctx: %v service: %s method: %s\n", md, req.Service(), req.Endpoint()) return l.Client.Call(ctx, req, rsp) } func NewLogWrapper(c client.Client) client.Client { return &logWrapper{c} } ``` ## Handler Wrapper Usage Here's a basic log wrapper for the handler ```go func NewLogWrapper(fn server.HandlerFunc) server.HandlerFunc { return func(ctx context.Context, req server.Request, rsp interface{}) error { log.Printf("[Log Wrapper] Before serving request method: %v", req.Endpoint()) err := fn(ctx, req, rsp) log.Printf("[Log Wrapper] After serving request") return err } } ```