转者按:本文介绍了如何hook一个http的处理函数,从而加入自定义的内容。
http.FileServer
and
was pleasantly surprised how easy it was to do.
Let’s start with a basic file server for /tmp
:
1 2 3 |
|
This starts up a local file server at :8080. How can we hook into this so we can run some code before file requests are served? Let’s look at the method signature for http.ListenAndServe
:
1
|
|
So it looks like http.FileServer
returns
a Handler
that knows how to serve files
given a root directory. Now let’s look at the Handler
interface:
1 2 3 |
|
Because of go’s granular interfaces, any object can be a Handler
so
long as it implements ServeHTTP
. It
seems all we need to do is construct our own Handler
that
wraps http.FileServer
’s handler. There’s
a built in helper for turning ordinary functions into handlers called http.HandlerFunc
:
1
|
|
Then we just wrap http.FileServer
like
so:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Go has a bunch of other builtin handlers like TimeoutHandler and RedirectHandler that can be mixed and matched the same way.
另一种方式参考https://github.com/philsong/golang_samples/blob/master/src/emvdecoder/emvdecoder.go
type TraceHandler struct { h http.Handler n int } func (r *TraceHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { r.n++ fmt.Printf("counter = %d\n", r.n) //why counter always zero fmt.Println("get", req.URL.Path, " from ", req.RemoteAddr) r.h.ServeHTTP(w, req) } func main() { port := "9090" //Default port if len(os.Args) > 1 { port = strings.Join(os.Args[1:2], "") } h := http.StripPrefix("/icclogs/", http.FileServer(http.Dir("./logs/"))) http.Handle("/icclogs/", &TraceHandler{h: h, n: 0}) println("Listening on port ", port, "...") err := http.ListenAndServe(":"+port, nil) //设置监听的端口 if err != nil { log.Fatal("ListenAndServe: ", err) } }
有疑问加站长微信联系(非本文作者)