内容简介:当构建 web 应用程序,可能对所有的请求会共享一些功能。例如我们每一个请求都会写入日志。在 go 语言 net/http 标准库中提供了中间件类似的函数 StripPrefix 和 TimeoutHandler。如何自己编写一个中间件呢?答案是
golang_real.jpg
当构建 web 应用程序,可能对所有的请求会共享一些功能。例如我们每一个请求都会写入日志。
- 打印 http 请求或返回的日志
- 压缩 http 请求的返回值
- 将 http 请求头保持一致
-
实现安全以及权限验证
Middleware-web.jpg
在 go 语言 net/http 标准库中提供了中间件类似的函数 StripPrefix 和 TimeoutHandler。
如何自己编写一个中间件呢?答案是
- 这个函数接收一个 http.Handler 作为参数,目的是可使用其他中间件或应用处理器,调用其他中间件或应用的方法就是调用其 HttpServe 的方法。
- 并且将 http.Handler 作为返回值,这样其他中间件可以使用 http.Handler 作为输入的参数,达到链式调用。
func middlewareHandler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 在执行应用处理器前编译中间件的逻辑 next.ServeHTTP(w, r) // 在执行应用处理器后将会执行的编译中间件的逻辑 }) }
从上面示例我们可以看出 go 语言是支持高阶函数,通过向下传递 http.Handler 来实现中间件。
package main import ( "fmt" "log" "net/http" "time" ) func logginHandler(next http.Handler) http.Handler{ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){ start := time.Now() log.Printf("Started %s %s",r.Method, r.URL.Path) next.ServeHTTP(w,r) log.Printf("Completed %s in %v", r.URL.Path, time.Since(start)) }) } func index(w http.ResponseWriter,r *http.Request ){ log.Println("Executing index handler") fmt.Fprintf(w,"welcome!") } func about(w http.ResponseWriter, r *http.Request){ log.Println("Executing about handler") fmt.Fprintf(w,"Go Middleware") } func iconHandler(w http.ResponseWriter, r *http.Request){ } func main() { http.HandleFunc("/favicon.ico", iconHandler) indexHandler := http.HandlerFunc(index) aboutHandler := http.HandlerFunc(about) http.Handle("/",logginHandler(indexHandler)) http.Handle("/about",logginHandler(aboutHandler)) server := &http.Server{ Addr:":8080", } log.Println("Listening...") server.ListenAndServe() }
- 上面的代码关键是 logginHandler 这个日志处理器,作为中间件会拦截请求,进行处理也就是输出日志,通过
next.ServeHTTP(w,r)
然后将请求向下进行传递 - 这里创建两个简单路由处理器
index
和about
。都是向客户端输出不同的文本。 -
http.Handle("/",logginHandler(indexHandler))
通过 logginHandler 函数进行包裹,从容我们日志中间件可以拦截到发起的请求进行一些业务逻辑,业务逻辑可以位于next.ServeHTTP(w,r)
之前或之后。通过下面的输出我们可以清晰可见代码执行的顺序。
Listening... Started GET / Executing index handler Completed / in 41.129µs Started GET / Executing index handler Completed / in 50.475µs Started GET /about Executing about handler Completed /about in 49.483µs
许多书都提供代码示例,个人建议是不要 copy 过来运行看效果,自己手 coding 就可以发现一些问题,同时可以思考为什么要这样编写代码。
通过上面示例我们了解如何写一个简单中间件,这个个人看来和 nodejs 实现中间件没有什么差别。实际开发中我们往往会有多个中间件来执行业务,那么这些中间件执行顺序也是我们值得考虑的问题。
package main import( "fmt" "log" "net/http" ) func middlewareFirst(next http.Handler) http.Handler{ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){ log.Println("MiddlewareFirst - before Handler") next.ServeHTTP(w,r) log.Println("MiddlewareFirst - after Handler") }) } func middlewareSecond(next http.Handler) http.Handler{ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){ log.Println("MiddlewareSecond - before Handler") if r.URL.Path == "/message"{ if r.URL.Query().Get("password") == "123"{ log.Println("Authorized to system...") next.ServeHTTP(w,r) }else{ log.Println("Failed to authorize to the system") return } }else{ next.ServeHTTP(w,r) } log.Println("MiddlewareScond - after Handler") }) } func index(w http.ResponseWriter, r *http.Request){ log.Println("Executed index Handler") fmt.Fprintf(w,"welcome") } func message(w http.ResponseWriter, r *http.Request){ log.Println("Executed message Handler") fmt.Fprintf(w,"message...") } func iconHandler(w http.ResponseWriter, r *http.Request){ } func main() { http.HandleFunc("/favicon",iconHandler) indexHandler := http.HandlerFunc(index) messageHandler := http.HandlerFunc(message) http.Handle("/",middlewareFirst(middlewareSecond(indexHandler))) http.Handle("/message",middlewareFirst(middlewareSecond(messageHandler))) server := &http.Server{ Addr:":8080", } log.Println("Listen...") server.ListenAndServe() }
在上面代码中其实也没有什么特别之处,就是我们创建了两个 middlewareFirst
和 middlewareSecond
两个中间件并且有一定先后顺序,然后在 middlewareSecond
中写了一个对访问权限校验的逻辑。大家可以尝试地去运行一下。
th-7.jpeg
以上所述就是小编给大家介绍的《golang 网络编程(5)中间件》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Art of Computer Programming, Volumes 1-3 Boxed Set
Donald E. Knuth / Addison-Wesley Professional / 1998-10-15 / USD 199.99
This multivolume work is widely recognized as the definitive description of classical computer science. The first three volumes have for decades been an invaluable resource in programming theory and p......一起来看看 《The Art of Computer Programming, Volumes 1-3 Boxed Set》 这本书的介绍吧!