链接 CAS 中间件和 httprouter() 路由

Chaining CAS middleware and httprouter() routing

我对一个可能很简单的问题深陷泥潭。我需要使用对第三方 CAS 身份验证服务的调用包装一个函数。我正在使用 go-cas 来执行此操作,并且在我开始添加路由要求之前一直有效。我选择了 Julien Schmidt 的 httprouter,不知何故我也需要让它与 go-cas 一起工作。

如果我没记错的话,我需要使用某种定制设计的中间件来从处理程序到处理程序。我认为链条需要像这样:

http.Handler -> func(http.ResponseWriter, *http.Request, httprouter.Params)

...第一个是 CAS 想要的,第二个是 httprouter 想要的。但是我现在很迷茫,不知道该做什么。

感谢任何建议!


在下面的代码中,调用...

router.Handler("GET", "/", client.HandleFunc(defaultHandler))

... 产生此错误:

"cannot use defaultHandler (type func(http.ResponseWriter, *http.Request, httprouter.Params)) as type func(http.ResponseWriter, *http.Request) in argument to client.HandleFunc"

这是无效代码:

package main

import (
    "fmt"
    "log"
    "net/http"
    "strings"
    "time"

    "github.com/go-cas/cas"
    "github.com/julienschmidt/httprouter"
)

func defaultHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
    if !cas.IsAuthenticated(r) {
        cas.RedirectToLogin(w, r)
    }

    pageID := ps.ByName("pageID")

    type pageModel struct {
        Title    string
        PageID   string
    }

    model := pageModel{
        Title:    "Seminars",
        PageID:    pageID,
    }
    render.ToBrowser(w, "views/index.html", &model)
}


func main() {

    u, _ := url.Parse("https://cas_example_server.com")

    client := cas.NewClient(&cas.Options{
        URL: u,
    })

    router := httprouter.New()

    //This line fails with the message:

    //"Cannot use defaultHandler (type func(http.ResponseWriter, *http.Request, httprouter.Params)) 
    //as type func(http.ResponseWriter, *http.Request) in argument to client.HandleFunc"

    router.Handler("GET", "/", client.HandleFunc(defaultHandler))

    err := http.ListenAndServe(":8080", router)
    if err != nil {
        panic(err)
    }

}

您的中间件可能使用请求上下文将数据传递给具有不同签名的处理程序:

import (
    "net/http"
    "net/url"

    "github.com/go-cas/cas"
    "github.com/julienschmidt/httprouter"
    "golang.org/x/net/context"
)

func defaultHandler(w http.ResponseWriter, r *http.Request) {
    if !cas.IsAuthenticated(r) {
        cas.RedirectToLogin(w, r)
    }

    ps := r.Context().Value("params").(httprouter.Params)

    // business logic
}


func main() {

    u, _ := url.Parse("https://cas_example_server.com")

    client := cas.NewClient(&cas.Options{
        URL: u,
    })

    router := httprouter.New()

    //This line fails with the message:

    //"Cannot use defaultHandler (type func(http.ResponseWriter, *http.Request, httprouter.Params))
    //as type func(http.ResponseWriter, *http.Request) in argument to client.HandleFunc"

    router.Handler("GET", "/", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
        newContext := context.WithValue(r.Context(), "params", ps)
        r.WithContext(newContext)
        client.HandleFunc(defaultHandler)(w, r)
    })

    err := http.ListenAndServe(":8080", router)
    if err != nil {
        panic(err)
    }

}

更新: 有许多有用的库可以像这样保存您的 http 处理程序堆栈 https://github.com/urfave/negroni