golangtc 源码阅读的启示
就像connect中间件一样要实现实现权限的检查,就把这个信息给带上建立一个 url,permission,handleFunc 的一张表,然后中间件就加在处理这张表的函数里。
比如url.go里面
/* URL和Handler的Mapping */ package gopher import ( "net/http" ) type Handler struct { URL string Permission int HandlerFunc http.HandlerFunc } var ( handlers = []Handler{ {"/", Everyone, indexHandler}, {"/about", Everyone, staticHandler("about.html")}, {"/faq", Everyone, staticHandler("faq.html")}, {"/timeline", Everyone, staticHandler("timeline.html")}, 。。。。。。。。。
。。。。。。。。。
{"/books", Everyone, booksHandler}, {"/book/{id}", Everyone, showBookHandler}, {"/download", Everyone, downloadHandler}, } )
然后再server.go里面
/* 读取配置文件,设置URL,启动服务器 */ package gopher import ( "fmt" "log" "net/http" "github.com/gorilla/mux" ) func handlerFun(handler Handler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if handler.Permission == Everyone { handler.HandlerFunc(w, r) } else if handler.Permission == Authenticated { _, ok := currentUser(r) if !ok { http.Redirect(w, r, "/signin", http.StatusFound) return } handler.HandlerFunc(w, r) } else if handler.Permission == Administrator { user, ok := currentUser(r) if !ok { http.Redirect(w, r, "/signin", http.StatusFound) return } if !user.IsSuperuser { message(w, r, "没有权限", "对不起,你没有权限进行该操作", "error") return } handler.HandlerFunc(w, r) } } } func StartServer() { http.Handle("/static/", http.FileServer(http.Dir("."))) r := mux.NewRouter() for _, handler := range handlers { r.HandleFunc(handler.URL, handlerFun(handler)) } http.Handle("/", r) fmt.Println("Server start on:", Config.Port) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", Config.Port), nil)) }
然后用闭包,把中间件加上去。再用range handlers来对应路由。加中间件感觉就像是往上套一层一层的闭包。
func renderTemplate(w http.ResponseWriter, r *http.Request, file string, data map[string]interface{}) { _, isPresent := data["signout"] // 如果isPresent==true,说明在执行登出操作 if !isPresent { // 加入用户信息 user, ok := currentUser(r) if ok { data["username"] = user.Username data["isSuperUser"] = user.IsSuperuser data["email"] = user.Email data["fansCount"] = len(user.Fans) data["followCount"] = len(user.Follow) } } data["utils"] = utils data["analyticsCode"] = analyticsCode data["shareCode"] = shareCode data["staticFileVersion"] = Config.StaticFileVersion flash, _ := store.Get(r, "flash") data["flash"] = flash data["goVersion"] = goVersion _, ok := data["active"] if !ok { data["active"] = "" } page := parseTemplate(file, data) w.Write(page) }
把负责view的render做成一个函数统一起来。
把download的内容配置成一个config里面的download文件,可以更好的管理要被下载的文件。