英文:
How to get url param in middleware go-chi
问题
我使用特定的中间件来处理特定的路由。
r.Route("/platform", func(r chi.Router) {
r.Use(authService.AuthMiddleware)
r.Get("/{id}/latest", RequestPlatformVersion)
})
现在我想在AuthMiddleware
中访问id
的URL参数。
func (s *Service) AuthMiddleware(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Println(chi.URLParam(r, "id"))
id := chi.URLParam(r, "id")
if id > 100 {
http.Error(w, errors.New("Error").Error(), http.StatusUnauthorized)
return
}
}
return http.HandlerFunc(fn)
}
然而,即使中间件正在运行并且调用了特定的路由,id
参数打印为空字符串。
英文:
I use a specific middleware for specific set of routes
r.Route("/platform", func(r chi.Router) {
r.Use(authService.AuthMiddleware)
r.Get("/{id}/latest", RequestPlatformVersion)
})
Now how can I access id
url param inside this AuthMiddleware
middleware
func (s *Service) AuthMiddleware(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Println(chi.URLParam(r, "id"))
id := chi.URLParam(r, "id")
if id > 100 {
http.Error(w, errors.New("Error").Error(), http.StatusUnauthorized)
return
}
}
return http.HandlerFunc(fn)
}
However, the id param prints as an empty string even though the middleware is being ran and a specific route is being called
答案1
得分: 6
你将chi.URLParam
放在路径参数{id}
之前,并且忘记在中间件中添加.ServeHTTP(w, r)
。如果你不加这个,你的请求将不会进入路由中的路径。
这是一个可工作的示例:
package main
import (
"fmt"
"net/http"
"github.com/go-chi/chi"
)
func AuthMiddleware(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Println(chi.URLParam(r, "id"))
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
func main() {
r := chi.NewRouter()
r.Route("/platform/{id}", func(r chi.Router) {
r.Use(AuthMiddleware)
r.Get("/latest", func(rw http.ResponseWriter, r *http.Request) {
fmt.Println("here ", chi.URLParam(r, "id")) // <- here
})
})
http.ListenAndServe(":8080", r)
}
我将{id}
移到了platform/{id}
,这样中间件就可以获取到id
路径值,并在中间件中添加了h.ServeHTTP(w, r)
。
尝试访问http://localhost:8080/platform/1/latest
,输出将会是:
1
here 1
更新:
在代码之后运行验证是不好的,你必须修复定义路径的方式,并将.ServeHTTP
移动到验证之后。
这是一个示例:
package main
import (
"errors"
"fmt"
"net/http"
"strconv"
"github.com/go-chi/chi"
)
func AuthMiddleware(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("中间件先执行,id: %+v\n", chi.URLParam(r, "id"))
id, _ := strconv.Atoi(chi.URLParam(r, "id"))
if id > 100 {
http.Error(w, errors.New("错误").Error(), http.StatusUnauthorized)
return
}
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
func main() {
r := chi.NewRouter()
// 这种方式也可以
// r.Route("/platform/{id}", func(r chi.Router) {
// r.Use(AuthMiddleware)
// r.Get("/latest", func(rw http.ResponseWriter, r *http.Request) {
// fmt.Println("second: ", chi.URLParam(r, "id")) // <- here
// })
// })
// 另一种解决方案(包装中间件)
r.Route("/platform", func(r chi.Router) {
r.Get("/{id}/latest", AuthMiddleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
fmt.Println("second: ", chi.URLParam(r, "id")) // <- here
})).ServeHTTP)
})
http.ListenAndServe(":8080", r)
}
英文:
You put your chi.URLParam
before the path param {id}
and you forgot to put .ServeHTTP(w, r)
at the middleware. If you don't put that thing, your request will not go inside the path inside the route.
this is the working example:
package main
import (
"fmt"
"net/http"
"github.com/go-chi/chi"
)
func AuthMiddleware(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Println(chi.URLParam(r, "id"))
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
func main() {
r := chi.NewRouter()
r.Route("/platform/{id}", func(r chi.Router) {
r.Use(AuthMiddleware)
r.Get("/latest", func(rw http.ResponseWriter, r *http.Request) {
fmt.Println("here ", chi.URLParam(r, "id")) // <- here
})
})
http.ListenAndServe(":8080", r)
}
I move the {id}
to platform/{id}
so the middleware got the id
path value, and add h.ServeHTTP(w, r)
inside the middleware.
try to access http://localhost:8080/platform/1/latest
the output will be:
1
here 1
UPDATE
It is not good to run the validation after the code, you must fix the way you define the path, and move the .ServeHTTP
after the validation.
This is the example:
package main
import (
"errors"
"fmt"
"net/http"
"strconv"
"github.com/go-chi/chi"
)
func AuthMiddleware(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("Middleware First, id: %+v\n", chi.URLParam(r, "id"))
id, _ := strconv.Atoi(chi.URLParam(r, "id"))
if id > 100 {
http.Error(w, errors.New("Error").Error(), http.StatusUnauthorized)
return
}
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
func main() {
r := chi.NewRouter()
// This works too ()
// r.Route("/platform/{id}", func(r chi.Router) {
// r.Use(AuthMiddleware)
// r.Get("/latest", func(rw http.ResponseWriter, r *http.Request) {
// fmt.Println("second: ", chi.URLParam(r, "id")) // <- here
// })
// })
// Other Solution (Wrapping Middleware)
r.Route("/platform", func(r chi.Router) {
r.Get("/{id}/latest", AuthMiddleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
fmt.Println("second: ", chi.URLParam(r, "id")) // <- here
})).ServeHTTP)
})
http.ListenAndServe(":8080", r)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论