I'm deep in the weeds on what's probably a simple problem. I need wrap a func with a call to a third-party CAS authenication service. I'm using go-cas to do that, and it worked until I started adding routing requirements. I chose Julien Schmidt's httprouter, and somehow I need to get that to work with go-cas too.
If I'm not mistaken, I need to use some kind of custom-designed middleware to go from handler to handler. I think the chain needs to go something like this:
http.Handler -> func(http.ResponseWriter, *http.Request, httprouter.Params)
...the first being what CAS wants, and the second being what httprouter wants. But I'm so lost now that I can't make heads or tails of what to do.
Thanks for any advice!
In the code below, the call to ...
router.Handler("GET", "/", client.HandleFunc(defaultHandler))
... produces this error:
"cannot use defaultHandler (type func(http.ResponseWriter, *http.Request, httprouter.Params)) as type func(http.ResponseWriter, *http.Request) in argument to client.HandleFunc"
Here's the non-working code:
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)
}
}
Your middleware may use request context to pass the data to the handler with different signature:
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)
}
}
UPDATE: There are a number of useful libraries to hold your http handlers stack like this https://github.com/urfave/negroni