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文件,可以更好的管理要被下载的文件。

posted @ 2014-02-24 09:26  ggaaooppeenngg  阅读(521)  评论(0编辑  收藏  举报