r, r *http.Request) {
fmt.Fprintf(w, " hello ! this's a http request \n method %v \n request url is %v ", r.Method, r.URL.String())
}
func main() {
// create middleware server
s := new(MiddlewareServe)
s.Handler = http.HandlerFunc(helloHandle)
s.Use(LogRequest)
// start server
fmt.Println(http.ListenAndServe(":3000", s))
}
运行
$ go run *.go
$ curl 127.0.0.1:3000
> hello ! this's a http request
> method GET
> request url is
# 输出日志
> 2016/04/24 02:28:12 GET 200 / use time 61.717µs content-length 64
$ curl 127.0.0.1:3000/hello/go
> hello ! this's a http request
> method GET
> request url is /hello/go
# 输出日志
> 2016/04/24 02:31:36 GET 200 /hello/go use time 28.207µs content-length 72
或者用浏览器请求地址查看效果
再加一个错误捕获中间件:
// ErrCatch catch and recover
func ErrCatch(w ResponseWriteReader, r *http.Request, next func()) {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
debug.PrintStack()
w.WriteHeader(http.StatusInternalServerError) // 500
}
}()
next()
}
测试
package main
import (
"fmt"
"net/http"
)
func helloHandle(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, " hello ! this's a http request \n method %v \n request url is %v \n", r.Method, r.URL.String())
}
func panicHandle(w http.ResponseWriter, r *http.Request) {
panic("help me !")
}
func main() {
// create middleware server
s := new(MiddlewareServe)
route := http.NewServeMux()
route.Handle("/hello", http.HandlerFunc(helloHandle))
route.Handle("/panic", http.HandlerFunc(panicHandle))
s.Handler = route
s.Use(LogRequest, ErrCatch)
// start server
fmt.Println(http.ListenAndServe(":3000", s))
}
运行
$ curl -i 127.0.0.1:3000/panic
> HTTP/1.1 500 Internal Server Error
> Date: Sat, 23 Apr 2016 18:51:12 GMT
> Content-Length: 0
> Content-Type: text/plain; charset=utf-8
# log
> help me !
> ... # debug.Stack
> 2016/04/24 02:51:12 GET 500 /panic use time 142.885µs content-length 0
$ curl -i 127.0.0.1:3000/hello/go
> HTTP/1.1 404 Not Found
> Content-Type: text/plain; charset=utf-8
> X-Content-Type-Options: nosniff
> Date: Sat, 23 Apr 2016 18:55:30 GMT
> Content-Length: 19
>
> 404 page not found
# log
2016/04/24 02:55:30 GET 404 /hello/go use time 41.14µs content-length 19
到这里,一个灵活的核心就实现出来了。我尽量只使用标准包,没有引入第三方包,希望这样可能帮助刚学习go的同学更加了解 net.http package,当然在真实使用中可以根据需要引入其他的符合 http.Handler 接口的 router 替代 ServeMux
有些同学可能已经看出来了,既然 MiddlewareServe 实现了 http.Handler 那就可以挂到 router 中。没错,这样就相当于可以为某个路径下单独定制 MiddlewareServe 了,比如某些接口需要权限校验,我会在下一篇中来尝试写权限校验。
涉及模版的调用我就不写了,因为这个确实是脚本语言更佳适合
全部代码的github地址: https://github.com/ifanfan/golearn/tree/master/websrv
自己写的第一篇博客希望以后可以坚持写下去