OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / go-kit / kit / transport / grpc / server.go
1 package grpc
2
3 import (
4         oldcontext "golang.org/x/net/context"
5         "google.golang.org/grpc"
6         "google.golang.org/grpc/metadata"
7
8         "github.com/go-kit/kit/endpoint"
9         "github.com/go-kit/kit/log"
10 )
11
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)
17 }
18
19 // Server wraps an endpoint and implements grpc.Handler.
20 type Server struct {
21         e      endpoint.Endpoint
22         dec    DecodeRequestFunc
23         enc    EncodeResponseFunc
24         before []ServerRequestFunc
25         after  []ServerResponseFunc
26         logger log.Logger
27 }
28
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.
34 func NewServer(
35         e endpoint.Endpoint,
36         dec DecodeRequestFunc,
37         enc EncodeResponseFunc,
38         options ...ServerOption,
39 ) *Server {
40         s := &Server{
41                 e:      e,
42                 dec:    dec,
43                 enc:    enc,
44                 logger: log.NewNopLogger(),
45         }
46         for _, option := range options {
47                 option(s)
48         }
49         return s
50 }
51
52 // ServerOption sets an optional parameter for servers.
53 type ServerOption func(*Server)
54
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...) }
59 }
60
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...) }
65 }
66
67 // ServerErrorLogger is used to log non-terminal errors. By default, no errors
68 // are logged.
69 func ServerErrorLogger(logger log.Logger) ServerOption {
70         return func(s *Server) { s.logger = logger }
71 }
72
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)
77         if !ok {
78                 md = metadata.MD{}
79         }
80
81         for _, f := range s.before {
82                 ctx = f(ctx, md)
83         }
84
85         request, err := s.dec(ctx, req)
86         if err != nil {
87                 s.logger.Log("err", err)
88                 return ctx, nil, err
89         }
90
91         response, err := s.e(ctx, request)
92         if err != nil {
93                 s.logger.Log("err", err)
94                 return ctx, nil, err
95         }
96
97         var mdHeader, mdTrailer metadata.MD
98         for _, f := range s.after {
99                 ctx = f(ctx, &mdHeader, &mdTrailer)
100         }
101
102         grpcResp, err := s.enc(ctx, response)
103         if err != nil {
104                 s.logger.Log("err", err)
105                 return ctx, nil, err
106         }
107
108         if len(mdHeader) > 0 {
109                 if err = grpc.SendHeader(ctx, mdHeader); err != nil {
110                         s.logger.Log("err", err)
111                         return ctx, nil, err
112                 }
113         }
114
115         if len(mdTrailer) > 0 {
116                 if err = grpc.SetTrailer(ctx, mdTrailer); err != nil {
117                         s.logger.Log("err", err)
118                         return ctx, nil, err
119                 }
120         }
121
122         return ctx, grpcResp, nil
123 }