Go 每日一库之 negroni( 二 )
// src/github.com/urfave/negroni/negroni.gotype HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {h(rw, r, next)}net/http中也有类似的代码 , 通过http.HandlerFunc封装func(http.ResponseWriter,*http.Request)从而实现接口http.Handler 。
negroni.With如果有多个中间件 , 每个都需要n.Use()有些繁琐 。 negroni提供了一个With()方法 , 它接受一个或多个negroni.Handler参数 , 返回一个新的对象:
func Middleware1(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {fmt.Println("Middleware1 begin")next(w, r)fmt.Println("Middleware1 end")}func Middleware2(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {fmt.Println("Middleware2 begin")next(w, r)fmt.Println("Middleware2 end")}func main() {mux := http.NewServeMux()mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Hello World!")})n := negroni.New()n = n.With(negroni.HandlerFunc(Middleware1),negroni.HandlerFunc(Middleware2),)n.UseHandler(mux)http.ListenAndServe(":3000", n)}RunNegroni对象提供了一个方便的Run()方法来运行服务器程序 。 它接受与http.ListenAndServe()一样的地址(Addr)参数:
func main() {mux := http.NewServeMux()mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Hello World!")})n := negroni.New()n.UseHandler(mux)n.Run(":3000")}如果未指定端口 , 那么尝试使用PORT环境变量 。 如果PORT环境变量也未设置 , 那么使用默认的端口:8080 。
作为http.Handler使用negroni很容易在net/http程序中使用 , negroni.Negroni对象可直接作为http.Handler传给相应的方法:
func main() {mux := http.NewServeMux()mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Hello World!")})n := negroni.Classic()n.UseHandler(mux)s :=Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36Recoverynegroni.Recovery可以捕获后续的中间件或处理器函数中出现的panic , 返回一个500的响应码:
func main() {mux := http.NewServeMux()mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {panic("internal server error")})n := negroni.New()n.Use(negroni.NewRecovery())n.UseHandler(mux)http.ListenAndServe(":3000", n)}请求时panic的堆栈会显示在浏览器中:
文章插图
这在开发环境比较有用 , 但是生成环境中不能泄露这个信息 。 这时可以设置PrintStack字段为false:
func main() {mux := http.NewServeMux()mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {panic("internal server error")})n := negroni.New()r := negroni.NewRecovery()r.PrintStack = falsen.Use(r)n.UseHandler(mux)http.ListenAndServe(":3000", n)}除了在控制台和浏览器中输出panic信息 , Recovery还提供了钩子函数 , 可以向其他服务上报panic , 如Sentry/Airbrake 。 当然上报的代码要自己写 。
func main() {mux := http.NewServeMux()mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {panic("internal server error")})n := negroni.New()r := negroni.NewRecovery()r.PanicHandlerFunc = reportToSentryn.Use(r)n.UseHandler(mux)http.ListenAndServe(":3000", n)}func reportToSentry(info *negroni.PanicInformation) {fmt.Println("sent to sentry")}设置PanicHandlerFunc之后 , 发生panic就会调用此函数 。
我们还可以对输出的格式进行设置 , 设置Formatter字段为negroni.HTMLPanicFormatter能让输出更好地在浏览器中呈现:
func main() {mux := http.NewServeMux()mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {panic("internal server error")})n := negroni.New()r := negroni.NewRecovery()r.Formatter = &negroni.HTMLPanicFormatter{}n.Use(r)n.UseHandler(mux)http.ListenAndServe(":3000", n)}效果:
文章插图
第三方中间件除了内置中间件外 , negroni还有很多第三方的中间件 。 完整列表看这里:#third-party-middleware 。
我们只介绍一个xrequestid , 它在每个请求中增加一个随机的Header:X-Request-Id 。
安装xrequestid:
$ go get github.com/pilu/xrequestid使用:
func main() {mux := http.NewServeMux()mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "X-Request-Id is `%s`", r.Header.Get("X-Request-Id"))})n := negroni.New()n.Use(xrequestid.New(16))n.UseHandler(mux)n.Run(":3000")}给每个请求增加一个 16 字节的X-Request-Id , 处理器函数中将这个X-Request-Id写入响应中 , 最后呈现在浏览器中 。 运行程序 , 在浏览器中输入localhost:3000查看效果 。
- 纠结|硬杠红米Note9Pro?iQOO Z1跌至1575,对比之后纠结了!
- 王兴称美团优选目前重点是建设核心能力;苏宁旗下云网万店融资60亿元;阿里小米拟增资居然之家|8点1氪 | 美团
- 长安|长安傍上华为这个大腿,市值暴涨500亿!可见华为影响力之大?
- 巅峰|realme巅峰之作:120Hz+陶瓷机身+5000mAh 做到了颜值与性能并存
- 蛋壳公寓|官媒发声:绝不能让“割韭菜者”一跑了之!
- 看过明年的iPhone之后,现在下手的都哭了
- 直播销售员|石家庄桥西区插上“互联网+”智慧发展之翼
- 精英|业务流程图怎么绘制?销售精英的经验之谈
- 砍单|iPhone12之后,拼多多又将iPhone12Pro拉下水
- 报名啦!宿迁开展第五届“十大科技之星”评选
