Gorilla Mux子路由器是否继承其父路由器的中间件?

huangapple go评论78阅读模式
英文:

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)
}

huangapple
  • 本文由 发表于 2022年6月21日 21:21:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/72701560.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定