在Go中简单实现HTTP服务中间件
程序员文章站
2022-04-27 20:53:00
通常一个简单http服务框架,就是注册一堆路由,然后根据路由调用不同的逻辑去处理。 但实际上可能有一些统一的处理对几乎所有的路由都涉及到,比如日志,比如权限等等。 那么这个时候搞一个中间做预处理,是一个不错的想法。 定义一个中间件单元: 然后将路由处理函数用中间件入口包裹起来: 最后注册你需要的中间 ......
通常一个简单http服务框架,就是注册一堆路由,然后根据路由调用不同的逻辑去处理。
但实际上可能有一些统一的处理对几乎所有的路由都涉及到,比如日志,比如权限等等。
那么这个时候搞一个中间做预处理,是一个不错的想法。
定义一个中间件单元:
1 package main 2 3 import ( 4 "net/http" 5 ) 6 7 // adaptorhandle middleware func type 8 type adaptorhandle func(w http.responsewriter, r *http.request) (next bool, err error) 9 10 // middlewareadaptor router middlewares mapped by url 11 type middlewareadaptor struct { 12 urls map[string][]adaptorhandle 13 } 14 15 // makemiddlewareadaptor make a middleware adaptor 16 func makemiddlewareadaptor() *middlewareadaptor { 17 mwa := &middlewareadaptor{ 18 urls: make(map[string][]adaptorhandle), 19 } 20 21 return mwa 22 } 23 24 // regist regist a adaptor 25 func (mw *middlewareadaptor) regist(url string, adaptor ...adaptorhandle) { 26 for _, adp := range adaptor { 27 mw.urls[url] = append(mw.urls[url], adp) 28 // mw.urls[url] = adp 29 } 30 } 31 32 // exec exec middleware adaptor funcs... 33 func (mw *middlewareadaptor) exec(url string, w http.responsewriter, r *http.request) (bool, error) { 34 if adps, ok := mw.urls[url]; ok { 35 for _, adp := range adps { 36 if next, err := adp(w, r); !next || (err != nil) { 37 return next, err 38 } 39 } 40 } 41 return true, nil 42 }
然后将路由处理函数用中间件入口包裹起来:
1 func middlewarehandler(next http.handler) http.handler { 2 return http.handlerfunc(func(w http.responsewriter, r *http.request) { 3 // before call handler 4 start := time.now() 5 do, _ := mwa.exec(r.url.path, w, r) // exec middleware 6 // call next handler 7 if do { 8 log.println("middleware done. next...") 9 next.servehttp(w, r) 10 } else { 11 log.println("middleware done.break...") 12 } 13 // after call handle 14 log.printf("comleted %s in %v", r.url.path, time.since(start)) 15 }) 16 } 17 18 mux.handle("/", middlewarehandler(&uplusrouterhandler{})) 19 20 type uplusrouterhandler struct { 21 } 22 23 func (rh *uplusrouterhandler) servehttp(w http.responsewriter, r *http.request) { 24 ... 25 }
最后注册你需要的中间件即可:
mwa = makemiddlewareadaptor() // init middleware mwa.regist("/", testmwafunc, testmwafunc2) // regist middleware ... func testmwafunc(w http.responsewriter, r *http.request) (bool, error) { log.println("我是第一个中间件...") log.printf("started %s %s", r.method, r.url.path) return true, nil } func testmwafunc2(w http.responsewriter, r *http.request) (bool, error) { log.println("我是第二个中间件...") return false, nil // return false,break follow-up actions. }
代码虽然简单,记录一个思路。