Package list golang-github-go-kit-kit / 46b3634
transport/http: Server constructor Peter Bourgon 6 years ago
7 changed file(s) with 196 addition(s) and 170 deletion(s). Raw diff Collapse all Expand all
147147 ctx := context.Background()
148148 svc := stringService{}
149149
150 uppercaseHandler := httptransport.Server{
151 Context: ctx,
152 Endpoint: makeUppercaseEndpoint(svc),
153 DecodeRequestFunc: decodeUppercaseRequest,
154 EncodeResponseFunc: encodeResponse,
155 }
156
157 countHandler := httptransport.Server{
158 Context: ctx,
159 Endpoint: makeCountEndpoint(svc),
160 DecodeRequestFunc: decodeCountRequest,
161 EncodeResponseFunc: encodeResponse,
162 }
150 uppercaseHandler := httptransport.NewServer(
151 ctx,
152 makeUppercaseEndpoint(svc),
153 decodeUppercaseRequest,
154 encodeResponse,
155 )
156
157 countHandler := httptransport.NewServer(
158 ctx,
159 makeCountEndpoint(svc),
160 decodeCountRequest,
161 encodeResponse,
162 )
163163
164164 http.Handle("/uppercase", uppercaseHandler)
165165 http.Handle("/count", countHandler)
253253 count = makeCountEndpoint(svc)
254254 count = loggingMiddleware(log.NewContext(logger).With("method", "count"))(count)
255255
256 uppercaseHandler := httptransport.Server{
257 Endpoint: uppercase,
256 uppercaseHandler := httptransport.Server(
258257 // ...
259 }
260
261 countHandler := httptransport.Server{
262 Endpoint: count,
258 uppercase,
263259 // ...
264 }
260 )
261
262 countHandler := httptransport.Server(
263 // ...
264 count,
265 // ...
266 )
265267 ```
266268
267269 It turns out that this technique is useful for a lot more than just logging.
326328 svc := stringService{}
327329 svc = loggingMiddleware{logger, svc}
328330
329 uppercaseHandler := httptransport.Server{
330 Endpoint: makeUppercaseEndpoint(svc),
331 // ...
332 }
333
334 countHandler := httptransport.Server{
335 Endpoint: makeCountEndpoint(svc),
336 // ...
337 }
331 uppercaseHandler := httptransport.NewServer(
332 // ...
333 makeUppercaseEndpoint(svc),
334 // ...
335 )
336
337 countHandler := httptransport.NewServer(
338 // ...
339 makeCountEndpoint(svc),
340 // ...
341 )
338342 }
339343 ```
340344
412416 svc = loggingMiddleware{logger, svc}
413417 svc = instrumentingMiddleware{requestCount, requestLatency, countResult, svc}
414418
415 uppercaseHandler := httptransport.Server{
416 Endpoint: makeUppercaseEndpoint(svc),
417 // ...
418 }
419
420 countHandler := httptransport.Server{
421 Endpoint: makeCountEndpoint(svc),
422 // ...
423 }
419 uppercaseHandler := httptransport.NewServer(
420 // ...
421 makeUppercaseEndpoint(svc),
422 // ...
423 )
424
425 countHandler := httptransport.NewServer(
426 // ...
427 makeCountEndpoint(svc),
428 // ...
429 )
424430
425431 http.Handle("/metrics", stdprometheus.Handler())
426432 }
138138
139139 sum = makeSumEndpoint(svc)
140140 sum = zipkin.AnnotateServer(newSumSpan, collector)(sum)
141 mux.Handle("/sum", httptransport.Server{
142 Context: root,
143 Endpoint: sum,
144 DecodeRequestFunc: server.DecodeSumRequest,
145 EncodeResponseFunc: server.EncodeSumResponse,
146 Before: []httptransport.RequestFunc{traceSum},
147 After: []httptransport.ResponseFunc{},
148 Logger: transportLogger,
149 })
141 mux.Handle("/sum", httptransport.NewServer(
142 root,
143 sum,
144 server.DecodeSumRequest,
145 server.EncodeSumResponse,
146 httptransport.ServerBefore(traceSum),
147 httptransport.ServerErrorLogger(transportLogger),
148 ))
150149
151150 concat = makeConcatEndpoint(svc)
152151 concat = zipkin.AnnotateServer(newConcatSpan, collector)(concat)
153 mux.Handle("/concat", httptransport.Server{
154 Context: root,
155 Endpoint: concat,
156 DecodeRequestFunc: server.DecodeConcatRequest,
157 EncodeResponseFunc: server.EncodeConcatResponse,
158 Before: []httptransport.RequestFunc{traceConcat},
159 After: []httptransport.ResponseFunc{},
160 Logger: transportLogger,
161 })
152 mux.Handle("/concat", httptransport.NewServer(
153 root,
154 concat,
155 server.DecodeConcatRequest,
156 server.EncodeConcatResponse,
157 httptransport.ServerBefore(traceConcat),
158 httptransport.ServerErrorLogger(transportLogger),
159 ))
162160
163161 _ = transportLogger.Log("addr", *httpAddr)
164162 errc <- http.ListenAndServe(*httpAddr, mux)
3535 ctx := context.Background()
3636 svc := stringService{}
3737
38 uppercaseHandler := httptransport.Server{
39 Context: ctx,
40 Endpoint: makeUppercaseEndpoint(svc),
41 DecodeRequestFunc: decodeUppercaseRequest,
42 EncodeResponseFunc: encodeResponse,
43 }
38 uppercaseHandler := httptransport.NewServer(
39 ctx,
40 makeUppercaseEndpoint(svc),
41 decodeUppercaseRequest,
42 encodeResponse,
43 )
4444
45 countHandler := httptransport.Server{
46 Context: ctx,
47 Endpoint: makeCountEndpoint(svc),
48 DecodeRequestFunc: decodeCountRequest,
49 EncodeResponseFunc: encodeResponse,
50 }
45 countHandler := httptransport.NewServer(
46 ctx,
47 makeCountEndpoint(svc),
48 decodeCountRequest,
49 encodeResponse,
50 )
5151
5252 http.Handle("/uppercase", uppercaseHandler)
5353 http.Handle("/count", countHandler)
4242 svc = loggingMiddleware{logger, svc}
4343 svc = instrumentingMiddleware{requestCount, requestLatency, countResult, svc}
4444
45 uppercaseHandler := httptransport.Server{
46 Context: ctx,
47 Endpoint: makeUppercaseEndpoint(svc),
48 DecodeRequestFunc: decodeUppercaseRequest,
49 EncodeResponseFunc: encodeResponse,
50 }
45 uppercaseHandler := httptransport.NewServer(
46 ctx,
47 makeUppercaseEndpoint(svc),
48 decodeUppercaseRequest,
49 encodeResponse,
50 )
5151
52 countHandler := httptransport.Server{
53 Context: ctx,
54 Endpoint: makeCountEndpoint(svc),
55 DecodeRequestFunc: decodeCountRequest,
56 EncodeResponseFunc: encodeResponse,
57 }
52 countHandler := httptransport.NewServer(
53 ctx,
54 makeCountEndpoint(svc),
55 decodeCountRequest,
56 encodeResponse,
57 )
5858
5959 http.Handle("/uppercase", uppercaseHandler)
6060 http.Handle("/count", countHandler)
5353 svc = loggingMiddleware(logger)(svc)
5454 svc = instrumentingMiddleware(requestCount, requestLatency, countResult)(svc)
5555
56 uppercaseHandler := httptransport.Server{
57 Context: ctx,
58 Endpoint: makeUppercaseEndpoint(svc),
59 DecodeRequestFunc: decodeUppercaseRequest,
60 EncodeResponseFunc: encodeResponse,
61 }
62 countHandler := httptransport.Server{
63 Context: ctx,
64 Endpoint: makeCountEndpoint(svc),
65 DecodeRequestFunc: decodeCountRequest,
66 EncodeResponseFunc: encodeResponse,
67 }
56 uppercaseHandler := httptransport.NewServer(
57 ctx,
58 makeUppercaseEndpoint(svc),
59 decodeUppercaseRequest,
60 encodeResponse,
61 )
62 countHandler := httptransport.NewServer(
63 ctx,
64 makeCountEndpoint(svc),
65 decodeCountRequest,
66 encodeResponse,
67 )
6868
6969 http.Handle("/uppercase", uppercaseHandler)
7070 http.Handle("/count", countHandler)
1010
1111 // Server wraps an endpoint and implements http.Handler.
1212 type Server struct {
13 // A background context must be provided.
14 context.Context
13 ctx context.Context
14 e endpoint.Endpoint
15 dec DecodeRequestFunc
16 enc EncodeResponseFunc
17 before []RequestFunc
18 after []ResponseFunc
19 errorEncoder func(w http.ResponseWriter, err error)
20 logger log.Logger
21 }
1522
16 // The endpoint that will be invoked.
17 endpoint.Endpoint
23 // NewServer constructs a new server, which implements http.Server and wraps
24 // the provided endpoint.
25 func NewServer(
26 ctx context.Context,
27 e endpoint.Endpoint,
28 dec DecodeRequestFunc,
29 enc EncodeResponseFunc,
30 options ...ServerOption,
31 ) *Server {
32 s := &Server{
33 ctx: ctx,
34 e: e,
35 dec: dec,
36 enc: enc,
37 errorEncoder: defaultErrorEncoder,
38 logger: log.NewNopLogger(),
39 }
40 for _, option := range options {
41 option(s)
42 }
43 return s
44 }
1845
19 // DecodeRequestFunc must be provided.
20 DecodeRequestFunc
46 // ServerOption sets an optional parameter for servers.
47 type ServerOption func(*Server)
2148
22 // EncodeResponseFunc must be provided.
23 EncodeResponseFunc
49 // ServerBefore functions are executed on the HTTP request object before the
50 // request is decoded.
51 func ServerBefore(before ...RequestFunc) ServerOption {
52 return func(s *Server) { s.before = before }
53 }
2454
25 // Before functions are executed on the HTTP request object before the
26 // request is decoded.
27 Before []RequestFunc
55 // ServerAfter functions are executed on the HTTP response writer after the
56 // endpoint is invoked, but before anything is written to the client.
57 func ServerAfter(after ...ResponseFunc) ServerOption {
58 return func(s *Server) { s.after = after }
59 }
2860
29 // After functions are executed on the HTTP response writer after the
30 // endpoint is invoked, but before anything is written to the client.
31 After []ResponseFunc
61 // ServerErrorEncoder is used to encode errors to the http.ResponseWriter
62 // whenever they're encountered in the processing of a request. Clients can
63 // use this to provide custom error formatting and response codes. By default,
64 // errors will be written as plain text with an appropriate, if generic,
65 // status code.
66 func ServerErrorEncoder(f func(w http.ResponseWriter, err error)) ServerOption {
67 return func(s *Server) { s.errorEncoder = f }
68 }
3269
33 // ErrorEncoder is used to encode errors to the http.ResponseWriter
34 // whenever they're encountered in the processing of a request. Clients
35 // can use this to provide custom error formatting and response codes. If
36 // ErrorEncoder is nil, the error will be written as plain text with
37 // an appropriate, if generic, status code.
38 ErrorEncoder func(w http.ResponseWriter, err error)
39
40 // Logger is used to log errors.
41 Logger log.Logger
70 // ServerErrorLogger is used to log non-terminal errors. By default, no errors
71 // are logged.
72 func ServerErrorLogger(logger log.Logger) ServerOption {
73 return func(s *Server) { s.logger = logger }
4274 }
4375
4476 // ServeHTTP implements http.Handler.
4577 func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
46 if s.ErrorEncoder == nil {
47 s.ErrorEncoder = defaultErrorEncoder
48 }
49
50 ctx, cancel := context.WithCancel(s.Context)
78 ctx, cancel := context.WithCancel(s.ctx)
5179 defer cancel()
5280
53 for _, f := range s.Before {
81 for _, f := range s.before {
5482 ctx = f(ctx, r)
5583 }
5684
57 request, err := s.DecodeRequestFunc(r)
85 request, err := s.dec(r)
5886 if err != nil {
59 _ = s.Logger.Log("err", err)
60 s.ErrorEncoder(w, badRequestError{err})
87 _ = s.logger.Log("err", err)
88 s.errorEncoder(w, badRequestError{err})
6189 return
6290 }
6391
64 response, err := s.Endpoint(ctx, request)
92 response, err := s.e(ctx, request)
6593 if err != nil {
66 _ = s.Logger.Log("err", err)
67 s.ErrorEncoder(w, err)
94 _ = s.logger.Log("err", err)
95 s.errorEncoder(w, err)
6896 return
6997 }
7098
71 for _, f := range s.After {
99 for _, f := range s.after {
72100 f(ctx, w)
73101 }
74102
75 if err := s.EncodeResponseFunc(w, response); err != nil {
76 _ = s.Logger.Log("err", err)
77 s.ErrorEncoder(w, err)
103 if err := s.enc(w, response); err != nil {
104 _ = s.logger.Log("err", err)
105 s.errorEncoder(w, err)
78106 return
79107 }
80108 }
88
99 "golang.org/x/net/context"
1010
11 "github.com/go-kit/kit/log"
1211 httptransport "github.com/go-kit/kit/transport/http"
1312 )
1413
1514 func TestServerBadDecode(t *testing.T) {
16 handler := httptransport.Server{
17 Context: context.Background(),
18 Endpoint: func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil },
19 DecodeRequestFunc: func(*http.Request) (interface{}, error) { return struct{}{}, errors.New("dang") },
20 EncodeResponseFunc: func(http.ResponseWriter, interface{}) error { return nil },
21 Logger: log.NewNopLogger(),
22 }
15 handler := httptransport.NewServer(
16 context.Background(),
17 func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil },
18 func(*http.Request) (interface{}, error) { return struct{}{}, errors.New("dang") },
19 func(http.ResponseWriter, interface{}) error { return nil },
20 )
2321 server := httptest.NewServer(handler)
2422 defer server.Close()
2523 resp, _ := http.Get(server.URL)
2927 }
3028
3129 func TestServerBadEndpoint(t *testing.T) {
32 handler := httptransport.Server{
33 Context: context.Background(),
34 Endpoint: func(context.Context, interface{}) (interface{}, error) { return struct{}{}, errors.New("dang") },
35 DecodeRequestFunc: func(*http.Request) (interface{}, error) { return struct{}{}, nil },
36 EncodeResponseFunc: func(http.ResponseWriter, interface{}) error { return nil },
37 Logger: log.NewNopLogger(),
38 }
30 handler := httptransport.NewServer(
31 context.Background(),
32 func(context.Context, interface{}) (interface{}, error) { return struct{}{}, errors.New("dang") },
33 func(*http.Request) (interface{}, error) { return struct{}{}, nil },
34 func(http.ResponseWriter, interface{}) error { return nil },
35 )
3936 server := httptest.NewServer(handler)
4037 defer server.Close()
4138 resp, _ := http.Get(server.URL)
4542 }
4643
4744 func TestServerBadEncode(t *testing.T) {
48 handler := httptransport.Server{
49 Context: context.Background(),
50 Endpoint: func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil },
51 DecodeRequestFunc: func(*http.Request) (interface{}, error) { return struct{}{}, nil },
52 EncodeResponseFunc: func(http.ResponseWriter, interface{}) error { return errors.New("dang") },
53 Logger: log.NewNopLogger(),
54 }
45 handler := httptransport.NewServer(
46 context.Background(),
47 func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil },
48 func(*http.Request) (interface{}, error) { return struct{}{}, nil },
49 func(http.ResponseWriter, interface{}) error { return errors.New("dang") },
50 )
5551 server := httptest.NewServer(handler)
5652 defer server.Close()
5753 resp, _ := http.Get(server.URL)
6864 }
6965 return http.StatusInternalServerError
7066 }
71 handler := httptransport.Server{
72 Context: context.Background(),
73 Endpoint: func(context.Context, interface{}) (interface{}, error) { return struct{}{}, errTeapot },
74 DecodeRequestFunc: func(*http.Request) (interface{}, error) { return struct{}{}, nil },
75 EncodeResponseFunc: func(http.ResponseWriter, interface{}) error { return nil },
76 ErrorEncoder: func(w http.ResponseWriter, err error) { w.WriteHeader(code(err)) },
77 Logger: log.NewNopLogger(),
78 }
67 handler := httptransport.NewServer(
68 context.Background(),
69 func(context.Context, interface{}) (interface{}, error) { return struct{}{}, errTeapot },
70 func(*http.Request) (interface{}, error) { return struct{}{}, nil },
71 func(http.ResponseWriter, interface{}) error { return nil },
72 httptransport.ServerErrorEncoder(func(w http.ResponseWriter, err error) { w.WriteHeader(code(err)) }),
73 )
7974 server := httptest.NewServer(handler)
8075 defer server.Close()
8176 resp, _ := http.Get(server.URL)
10196 stepch = make(chan bool)
10297 endpoint = func(context.Context, interface{}) (interface{}, error) { <-stepch; return struct{}{}, nil }
10398 response = make(chan *http.Response)
104 handler = httptransport.Server{
105 Context: ctx,
106 Endpoint: endpoint,
107 DecodeRequestFunc: func(*http.Request) (interface{}, error) { return struct{}{}, nil },
108 EncodeResponseFunc: func(http.ResponseWriter, interface{}) error { return nil },
109 Before: []httptransport.RequestFunc{func(ctx context.Context, r *http.Request) context.Context { return ctx }},
110 After: []httptransport.ResponseFunc{func(ctx context.Context, w http.ResponseWriter) { return }},
111 Logger: log.NewNopLogger(),
112 }
99 handler = httptransport.NewServer(
100 ctx,
101 endpoint,
102 func(*http.Request) (interface{}, error) { return struct{}{}, nil },
103 func(http.ResponseWriter, interface{}) error { return nil },
104 httptransport.ServerBefore(func(ctx context.Context, r *http.Request) context.Context { return ctx }),
105 httptransport.ServerAfter(func(ctx context.Context, w http.ResponseWriter) { return }),
106 )
113107 )
114108 go func() {
115109 server := httptest.NewServer(handler)