17 | 17 |
before []RequestFunc
|
18 | 18 |
after []ServerResponseFunc
|
19 | 19 |
errorEncoder ErrorEncoder
|
|
20 |
finalizer ServerFinalizerFunc
|
20 | 21 |
logger log.Logger
|
21 | 22 |
}
|
22 | 23 |
|
|
68 | 69 |
}
|
69 | 70 |
|
70 | 71 |
// ServerErrorLogger is used to log non-terminal errors. By default, no errors
|
71 | |
// are logged.
|
|
72 |
// are logged. This is intended as a diagnostic measure. Finer-grained control
|
|
73 |
// of error handling, including logging in more detail, should be performed in a
|
|
74 |
// custom ServerErrorEncoder or ServerFinalizer, both of which have access to
|
|
75 |
// the context.
|
72 | 76 |
func ServerErrorLogger(logger log.Logger) ServerOption {
|
73 | 77 |
return func(s *Server) { s.logger = logger }
|
|
78 |
}
|
|
79 |
|
|
80 |
// ServerFinalizer is executed at the end of every HTTP request.
|
|
81 |
// By default, no finalizer is registered.
|
|
82 |
func ServerFinalizer(f ServerFinalizerFunc) ServerOption {
|
|
83 |
return func(s *Server) { s.finalizer = f }
|
74 | 84 |
}
|
75 | 85 |
|
76 | 86 |
// ServeHTTP implements http.Handler.
|
77 | 87 |
func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
78 | 88 |
ctx := s.ctx
|
|
89 |
|
|
90 |
if s.finalizer != nil {
|
|
91 |
iw := &interceptingWriter{w, http.StatusOK}
|
|
92 |
defer func() { s.finalizer(ctx, iw.code, r) }()
|
|
93 |
w = iw
|
|
94 |
}
|
79 | 95 |
|
80 | 96 |
for _, f := range s.before {
|
81 | 97 |
ctx = f(ctx, r)
|
|
115 | 131 |
// for their own error types. See the example shipping/handling service.
|
116 | 132 |
type ErrorEncoder func(ctx context.Context, err error, w http.ResponseWriter)
|
117 | 133 |
|
|
134 |
// ServerFinalizerFunc can be used to perform work at the end of an HTTP
|
|
135 |
// request, after the response has been written to the client. The principal
|
|
136 |
// intended use is for request logging.
|
|
137 |
type ServerFinalizerFunc func(ctx context.Context, code int, r *http.Request)
|
|
138 |
|
118 | 139 |
func defaultErrorEncoder(_ context.Context, err error, w http.ResponseWriter) {
|
119 | 140 |
switch e := err.(type) {
|
120 | 141 |
case Error:
|
|
130 | 151 |
http.Error(w, err.Error(), http.StatusInternalServerError)
|
131 | 152 |
}
|
132 | 153 |
}
|
|
154 |
|
|
155 |
type interceptingWriter struct {
|
|
156 |
http.ResponseWriter
|
|
157 |
code int
|
|
158 |
}
|
|
159 |
|
|
160 |
// WriteHeader may not be explicitly called, so care must be taken to
|
|
161 |
// initialize w.code to its default value of http.StatusOK.
|
|
162 |
func (w *interceptingWriter) WriteHeader(code int) {
|
|
163 |
w.code = code
|
|
164 |
w.ResponseWriter.WriteHeader(code)
|
|
165 |
}
|