问题: 无法从中间件访问mux.CurrentRoute(r).GetName()。 (虽然我能够从我的中间件访问它,但我必须改变我的中间件的工作方式,因为它以前无法访问请求)。所以我已经搞砸了一些事情,我不知道如何回到可以访问路线名称的工作状态。
非常感谢任何帮助!
错误:
runtime error: invalid memory address or nil pointer dereference
代码:
func main() {
var (
err error
r *mux.Router
devRouter *mux.Router
usersRouter *mux.Router
brandsRouter *mux.Router
)
defer db.Close()
defer store.Close()
r = mux.NewRouter()
devRouter = r.PathPrefix("/api/v1/dev").Subrouter()
usersRouter = r.PathPrefix("/api/v1/users").Subrouter()
brandsRouter = r.PathPrefix("/api/v1/brands").Subrouter()
// development endpoints
devRouter.HandleFunc("/db/seed", devDbSeed)
...
// users
usersRouter.HandleFunc("/create", usersCreateHandlerFunc).Methods("POST").Name("USERS_CREATE")
...
// brands
brandsRouter.HandleFunc("/create", brandsCreateHandlerFunc).Methods("POST").Name("BRANDS_CREATE")
...
// products
brandsRouter.HandleFunc("/{brand_id:[0-9]+}/products", brandsProductsListHandlerFunc).Methods("GET").Name("BRANDS_PRODUCTS_LIST")
...
// mwAuthorize and mwAuthenticate basically work the same
mw := []func(http.Handler) http.Handler{mwAuthenticate, mwAuthorize}
http.Handle("/", use(r, mw...))
err = http.ListenAndServe(":9000", nil)
if err != nil {
logIt(err)
}
}
func use(h http.Handler, mw ...func(http.Handler) http.Handler) http.Handler {
// exec order: mw[0],mw[1],mw[N]...
for i := len(mw) - 1; i >= 0; i-- {
h = mw[i](h)
}
return h
}
func mwAuthorize(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if true != authorize(r) {
w.WriteHeader(http.StatusForbidden)
return
} else {
next.ServeHTTP(w, r)
}
})
}
func authorize(r *http.Request) (isAuthorized bool) {
isAuthorized = false
/**
This is where it's failing!
*/
routeName := mux.CurrentRoute(r).GetName()
switch routeName {
case "USERS_CREATE":
// route-specific authorization
break
...
default:
break
}
return
}
更新(2015-01-04 @美国东部时间下午4:49): 因此,在删除中间件(或者至少注释掉试图读取mux.CurrentRoute的部分)之后,我能够从目标handlerfunc中检索路由名称(例如:usersCreateHandlerFunc或brandsCreateHandlerFunc)。这并没有解决我的问题(我仍然希望在中间件中执行身份验证/授权而不是每个handlerfunc),我有一种预感让我知道* mux.Router isn&#39 ;在我的中间件中可用,直到最后的.ServeHTTP调用。 (或者沿着这些方向......)
更新(2015-01-04 @美国东部时间下午5:41): 尝试使用Negroni作为中间件组件的不同(尽管不太优选)方向。当我尝试获取mux.CurrentRoute时,仍然会收到nil-pointer错误。
更新(2015-01-04 @美国东部时间下午6:17): 我能够从中间件函数访问请求(例如:r.URL),但仍然没有运气访问mux.Route(例如:mux.CurrentRoute(r))。在了解多路复用源之后,我认为这是因为当前的多路复用上下文没有设置,因为路由器还没有执行匹配器(因此它没有知道它在中间件完成之后的当前路径是什么。但是,我仍然不确定如何解决此问题,或重新构建我的代码来处理此问题。
答案 0 :(得分:1)
CurrentRoute返回当前请求的匹配路由(如果有)。这仅在匹配路由的处理程序内部调用时才有效,因为匹配的路由存储在请求上下文[...]
中
在您的示例中,您的package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
var (
err error
r *mux.Router
devRouter *mux.Router
)
func devDbSeed(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "devDbSeed")
return
}
func main() {
r = mux.NewRouter()
devRouter = r.PathPrefix("/api/v1/dev").Subrouter()
// mwAuthorize and mwAuthenticate basically work the same
mw := []func(http.Handler) http.Handler{mwAuthenticate, mwAuthorize}
// development endpoints
devRouter.Handle("/db/seed", use(http.HandlerFunc(devDbSeed), mw...)).Name("foo")
// Send all requests into the mux router
err = http.ListenAndServe(":9000", r)
if err != nil {
log.Fatal(err)
}
}
func use(h http.Handler, mw ...func(http.Handler) http.Handler) http.Handler {
// exec order: mw[0],mw[1],mw[N]...
for i := len(mw) - 1; i >= 0; i-- {
h = mw[i](h)
}
return h
}
func mwAuthorize(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !authorize(r) {
w.WriteHeader(http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
func mwAuthenticate(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
})
}
func authorize(r *http.Request) (isAuthorized bool) {
isAuthorized = false
handlerName := "UNKNOWN"
if route := mux.CurrentRoute(r); route != nil {
routeName := route.GetName()
if routeName != "" {
handlerName = routeName
}
}
log.Println(handlerName)
switch handlerName {
case "USERS_CREATE":
// route-specific authorization
log.Println("USERS_CREATE")
break
default:
break
}
return
}
链附加到路径“/”而不使用gorilla mux。这意味着当请求通过处理程序时,它还没有通过gorilla mux路由器。
尝试以下操作(您的示例已被删除):
sqlSave(sqlOdbc, insertRows, tablename = "Products",
append = TRUE, verbose = TRUE,
colnames = c("Code","DefaultSupplierSku","Name","Size","DefaultSupplierID","BrandID","ProductTypeID","BuyPrice","SellPrice")
)
答案 1 :(得分:1)
那:
routeName := mux.CurrentRoute(r).GetName()
r
是*http.Request
的地方。不要忘记导入"github.com/gorilla/mux"
。请记住,要使用此名称,必须在定义时给您一个路由名称
答案 2 :(得分:0)
我有同样的问题,我以这种方式解决了:
var match mux.RouteMatch
routeExists := s.Router.Match(r, &match)
if routeExists && match.Route.GetName(){
routeName := match.Route.GetName()
}
当我定义路线时,我添加了.Name("route/:param")
,其中route/:param
是我的路线。