4 oldcontext "golang.org/x/net/context"
5 "google.golang.org/grpc"
6 "google.golang.org/grpc/metadata"
8 "github.com/go-kit/kit/endpoint"
9 "github.com/go-kit/kit/log"
12 // Handler which should be called from the gRPC binding of the service
13 // implementation. The incoming request parameter, and returned response
14 // parameter, are both gRPC types, not user-domain.
15 type Handler interface {
16 ServeGRPC(ctx oldcontext.Context, request interface{}) (oldcontext.Context, interface{}, error)
19 // Server wraps an endpoint and implements grpc.Handler.
23 enc EncodeResponseFunc
24 before []ServerRequestFunc
25 after []ServerResponseFunc
29 // NewServer constructs a new server, which implements wraps the provided
30 // endpoint and implements the Handler interface. Consumers should write
31 // bindings that adapt the concrete gRPC methods from their compiled protobuf
32 // definitions to individual handlers. Request and response objects are from the
33 // caller business domain, not gRPC request and reply types.
36 dec DecodeRequestFunc,
37 enc EncodeResponseFunc,
38 options ...ServerOption,
44 logger: log.NewNopLogger(),
46 for _, option := range options {
52 // ServerOption sets an optional parameter for servers.
53 type ServerOption func(*Server)
55 // ServerBefore functions are executed on the HTTP request object before the
56 // request is decoded.
57 func ServerBefore(before ...ServerRequestFunc) ServerOption {
58 return func(s *Server) { s.before = append(s.before, before...) }
61 // ServerAfter functions are executed on the HTTP response writer after the
62 // endpoint is invoked, but before anything is written to the client.
63 func ServerAfter(after ...ServerResponseFunc) ServerOption {
64 return func(s *Server) { s.after = append(s.after, after...) }
67 // ServerErrorLogger is used to log non-terminal errors. By default, no errors
69 func ServerErrorLogger(logger log.Logger) ServerOption {
70 return func(s *Server) { s.logger = logger }
73 // ServeGRPC implements the Handler interface.
74 func (s Server) ServeGRPC(ctx oldcontext.Context, req interface{}) (oldcontext.Context, interface{}, error) {
75 // Retrieve gRPC metadata.
76 md, ok := metadata.FromIncomingContext(ctx)
81 for _, f := range s.before {
85 request, err := s.dec(ctx, req)
87 s.logger.Log("err", err)
91 response, err := s.e(ctx, request)
93 s.logger.Log("err", err)
97 var mdHeader, mdTrailer metadata.MD
98 for _, f := range s.after {
99 ctx = f(ctx, &mdHeader, &mdTrailer)
102 grpcResp, err := s.enc(ctx, response)
104 s.logger.Log("err", err)
108 if len(mdHeader) > 0 {
109 if err = grpc.SendHeader(ctx, mdHeader); err != nil {
110 s.logger.Log("err", err)
115 if len(mdTrailer) > 0 {
116 if err = grpc.SetTrailer(ctx, mdTrailer); err != nil {
117 s.logger.Log("err", err)
122 return ctx, grpcResp, nil