英文:
Does gorilla mux subrouters inherit the middlewares of their parent router?
问题
整个问题都在标题中。
我在 Stack Overflow 上搜索了一下,看看子路由器是否会使用其父级的中间件,即在父级路由器上使用 Use()
方法应用中间件,但我找不到一个清晰简明的答案。
我在包文档中也找不到这方面的信息,所以我决定进行测试,并在这里为所有遇到同样情况的人发布一个问题和答案。
在下面的代码示例中,请求 /john
会触发 logMiddleware 吗?
mainRouter := mux.NewRouter()
mainRouter.Use(logMiddleware)
subRouter := mainRouter.PathPrefix("/users/").Subrouter()
subRouter.Handle("/john", johnHandler())
英文:
The whole question is in the title.
I was searching on SO if a subrouter will use a middleware of its parent, in the case the middleware is applied to the parent router with the method Use()
, but I couldn't find a clear concise answer.
I couldn't find that information in the package documentation either, so I decided to test it and post a question and an answer here for everyone in the same case.
In the following code sample, does requesting on /john
will trigger the logMiddleware ?
mainRouter := mux.NewRouter()
mainRouter.Use(logMiddleware)
subRouter := mainRouter.PathPrefix("/users/").Subrouter()
subRouter.Handle("/john", johnHandler())
答案1
得分: 1
是的,mux子路由器在使用Use()
方法应用时会继承其父路由器的中间件。
以下是我创建的测试代码,你可以在你喜欢的IDE中尝试:
路由器代码
package so
import (
"context"
"net/http"
"github.com/gorilla/mux"
)
func newRouter(useMainMiddleware bool) mux.Router {
mainRouter := mux.NewRouter()
if useMainMiddleware {
mainRouter.Use(middleware)
}
subRouter := mainRouter.PathPrefix("/users/").Subrouter()
subRouter.Handle("/test", testHandler())
return *mainRouter
}
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r = r.WithContext(context.WithValue(r.Context(), "is_using_middleware", true))
next.ServeHTTP(w, r)
})
}
func testHandler() http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
if using, castOk := r.Context().Value("is_using_middleware").(bool); castOk && using {
w.WriteHeader(http.StatusOK)
return
}
w.WriteHeader(http.StatusInternalServerError)
return
},
)
}
测试文件
package so
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSubrouterWithMiddleware(t *testing.T) {
// GIVEN
request := httptest.NewRequest(http.MethodGet, "/users/test", nil)
recorder := httptest.NewRecorder()
router := newRouter(true) // 使用中间件
// WHEN
router.ServeHTTP(recorder, request)
// THEN
assert.Equal(t, http.StatusOK, recorder.Result().StatusCode)
}
func TestSubrouterWithoutMiddleware(t *testing.T) {
// GIVEN
request := httptest.NewRequest(http.MethodGet, "/users/test", nil)
recorder := httptest.NewRecorder()
router := newRouter(false) // 不使用中间件
// WHEN
router.ServeHTTP(recorder, request)
// THEN
assert.Equal(t, http.StatusInternalServerError, recorder.Result().StatusCode)
}
希望对你有所帮助!
英文:
Yes, mux subrouters inherit their parent's middlewares when applied with Use()
method.
Here is the test I created in case you want to try in your favorite IDE :
router code
package so
import (
"context"
"net/http"
"github.com/gorilla/mux"
)
func newRouter(useMainMiddleware bool) mux.Router {
mainRouter := mux.NewRouter()
if useMainMiddleware {
mainRouter.Use(middleware)
}
subRouter := mainRouter.PathPrefix("/users/").Subrouter()
subRouter.Handle("/test", testHandler())
return *mainRouter
}
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r = r.WithContext(context.WithValue(r.Context(), "is_using_middleware", true))
next.ServeHTTP(w, r)
})
}
func testHandler() http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
if using, castOk := r.Context().Value("is_using_middleware").(bool); castOk && using {
w.WriteHeader(http.StatusOK)
return
}
w.WriteHeader(http.StatusInternalServerError)
return
},
)
}
test file
package so
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSubrouterWithMiddleware(t *testing.T) {
// GIVEN
request := httptest.NewRequest(http.MethodGet, "/users/test", nil)
recorder := httptest.NewRecorder()
router := newRouter(true) // using a middleware
// WHEN
router.ServeHTTP(recorder, request)
// THEN
assert.Equal(t, http.StatusOK, recorder.Result().StatusCode)
}
func TestSubrouterWithoutMiddleware(t *testing.T) {
// GIVEN
request := httptest.NewRequest(http.MethodGet, "/users/test", nil)
recorder := httptest.NewRecorder()
router := newRouter(false) // not using a middleware
// WHEN
router.ServeHTTP(recorder, request)
// THEN
assert.Equal(t, http.StatusInternalServerError, recorder.Result().StatusCode)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论