这个例子将帮助你捕获响应状态代码和正文大小,然后记录它。如果你愿意,你也可以记录与请求有关的数据,但这不在本篇文章的范围之内。
响应写入器
package response
import (
"bufio"
"fmt"
"net"
"net/http"
)
// Acts as an adapter for `http.ResponseWriter` type to store response status
// code and size.
type ResponseWriter struct {
http.ResponseWriter
code int
size int
}
// Returns a new `ResponseWriter` type by decorating `http.ResponseWriter` type.
func NewResponseWriter(w http.ResponseWriter) *ResponseWriter {
return &ResponseWriter{
ResponseWriter: w,
}
}
// Overrides `http.ResponseWriter` type.
func (r *ResponseWriter) WriteHeader(code int) {
if r.Code() == 0 {
r.code = code
r.ResponseWriter.WriteHeader(code)
}
}
// Overrides `http.ResponseWriter` type.
func (r *ResponseWriter) Write(body []byte) (int, error) {
if r.Code() == 0 {
r.WriteHeader(http.StatusOK)
}
var err error
r.size, err = r.ResponseWriter.Write(body)
return r.size, err
}
// Overrides `http.Flusher` type.
func (r *ResponseWriter) Flush() {
if fl, ok := r.ResponseWriter.(http.Flusher); ok {
if r.Code() == 0 {
r.WriteHeader(http.StatusOK)
}
fl.Flush()
}
}
// Overrides `http.Hijacker` type.
func (r *ResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
hj, ok := r.ResponseWriter.(http.Hijacker)
if !ok {
return nil, nil, fmt.Errorf("the hijacker interface is not supported")
}
return hj.Hijack()
}
// Returns response status code.
func (r *ResponseWriter) Code() int {
return r.code
}
// Returns response size.
func (r *ResponseWriter) Size() int {
return r.size
}
访问记录器
package middleware
import (
"log"
"net/http"
"response"
)
// AccessLoger helps logging request and response related data.
func AccessLoger(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rw := response.NewResponseWriter(w)
h.ServeHTTP(rw, r)
log.Println("status:", rw.Code(), "size:", rw.Size(), "bytes")
})
}
服务器
package http
import (
"net/http"
)
// NewServer returns `http.Server` pointer type.
func NewServer(address string, handler http.Handler) *http.Server {
return &http.Server{
Addr: address,
Handler: AccessLoger(handler),
}
}
测试
如果你向你的一个端点发送一个请求的例子,日志应该看起来像下面这样:
2021/01/27 17:19:39 status: 200 size: 63 bytes