为什么我会得到这个适配器接口模式的无限循环
Why would I get an infinite loop with this Adapter Interface Pattern
我需要将现有的 API 接口替换为考虑传入 Auth 令牌并为传出服务调用发出机器对机器令牌的接口。
总而言之,这是一个使用 gorilla/mux 路由框架的 API,我只是将端点添加到 mux.NewRouter()。没有什么特别的......还;)。
我一直在尝试几种不同的模式,但似乎最吸引人的是 Mat Ryer 在 https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81 and https://go-talks.appspot.com/github.com/matryer/golanguk/building-apis.slide#30
中派生的适配器接口
总而言之,在没有直接逻辑的情况下,我做了以下操作,当我 运行 来自 Postman 的端点时陷入无限循环。
{"level":"info","msg":"New Relic Checkpoint!!!
/endpoint","time":"2019-08-19T14:28:27-05:00"}
{"level":"info","msg":"Security Checkpoint!!!
/endpoint","time":"2019-08-19T14:28:27-05:00"}
{"level":"info","msg":"Header Checkpoint!!!
/endpoint","time":"2019-08-19T14:28:27-05:00"}
{"level":"info","msg":"New Relic Checkpoint!!!
/endpoint","time":"2019-08-19T14:28:27-05:00"}
{"level":"info","msg":"Security Checkpoint!!!
/endpoint","time":"2019-08-19T14:28:27-05:00"}
{"level":"info","msg":"Header Checkpoint!!!
/endpoint","time":"2019-08-19T14:28:27-05:00"}
r.Handle(endpoint.Path(), Adapt(r, NewRelicAdapter(endpoint), SecurityAdapter(endpoint), WithHeader(endpoint)))
Adapter Interface建立如下...
type Adapter func(http.Handler) http.Handler
func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
for _, adapter := range reverseAdapters(adapters) {
h = adapter(h)
}
return h
}
func NewRelicAdapter(endpoint rest.Endpoint) Adapter {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logrus.Infof("New Relic Checkpoint!!! %v", endpoint.Path())
h.ServeHTTP(w, r)
})
}
}
func SecurityAdapter(endpoint rest.Endpoint) Adapter {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logrus.Infof("Security Checkpoint!!! %v", endpoint.Path())
h.ServeHTTP(w, r)
})
}
}
func WithHeader(endpoint rest.Endpoint) Adapter {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logrus.Infof("Header Checkpoint!!! %v", endpoint.Path())
h.ServeHTTP(w, r)
})
}
}
func reverseAdapters(adapters []Adapter) []Adapter {
for i := 0; i < len(adapters)/2; i++ {
j := len(adapters) - i - 1
adapters[i], adapters[j] = adapters[j], adapters[i]
}
return adapters
}
在我详细了解每个适配器将要做什么之前,如果知道为什么会循环,我将非常感激。
我 认为 这是因为您的处理程序链以 r 结尾,实际上变为:
r.Handle(path, r)
您必须在某处有一个实际的处理程序来处理调用,因此您的设置应如下所示:
r.Handle(path, Adapt(theHandler, adapter1, adapter2, adapter3))
但是,既然您说您正在使用 gorilla/mux,那么您可以通过另一种方式来实现。看看Router.Use
我需要将现有的 API 接口替换为考虑传入 Auth 令牌并为传出服务调用发出机器对机器令牌的接口。
总而言之,这是一个使用 gorilla/mux 路由框架的 API,我只是将端点添加到 mux.NewRouter()。没有什么特别的......还;)。
我一直在尝试几种不同的模式,但似乎最吸引人的是 Mat Ryer 在 https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81 and https://go-talks.appspot.com/github.com/matryer/golanguk/building-apis.slide#30
中派生的适配器接口总而言之,在没有直接逻辑的情况下,我做了以下操作,当我 运行 来自 Postman 的端点时陷入无限循环。
{"level":"info","msg":"New Relic Checkpoint!!! /endpoint","time":"2019-08-19T14:28:27-05:00"} {"level":"info","msg":"Security Checkpoint!!! /endpoint","time":"2019-08-19T14:28:27-05:00"} {"level":"info","msg":"Header Checkpoint!!! /endpoint","time":"2019-08-19T14:28:27-05:00"} {"level":"info","msg":"New Relic Checkpoint!!! /endpoint","time":"2019-08-19T14:28:27-05:00"} {"level":"info","msg":"Security Checkpoint!!! /endpoint","time":"2019-08-19T14:28:27-05:00"} {"level":"info","msg":"Header Checkpoint!!! /endpoint","time":"2019-08-19T14:28:27-05:00"}
r.Handle(endpoint.Path(), Adapt(r, NewRelicAdapter(endpoint), SecurityAdapter(endpoint), WithHeader(endpoint)))
Adapter Interface建立如下...
type Adapter func(http.Handler) http.Handler
func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
for _, adapter := range reverseAdapters(adapters) {
h = adapter(h)
}
return h
}
func NewRelicAdapter(endpoint rest.Endpoint) Adapter {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logrus.Infof("New Relic Checkpoint!!! %v", endpoint.Path())
h.ServeHTTP(w, r)
})
}
}
func SecurityAdapter(endpoint rest.Endpoint) Adapter {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logrus.Infof("Security Checkpoint!!! %v", endpoint.Path())
h.ServeHTTP(w, r)
})
}
}
func WithHeader(endpoint rest.Endpoint) Adapter {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logrus.Infof("Header Checkpoint!!! %v", endpoint.Path())
h.ServeHTTP(w, r)
})
}
}
func reverseAdapters(adapters []Adapter) []Adapter {
for i := 0; i < len(adapters)/2; i++ {
j := len(adapters) - i - 1
adapters[i], adapters[j] = adapters[j], adapters[i]
}
return adapters
}
在我详细了解每个适配器将要做什么之前,如果知道为什么会循环,我将非常感激。
我 认为 这是因为您的处理程序链以 r 结尾,实际上变为:
r.Handle(path, r)
您必须在某处有一个实际的处理程序来处理调用,因此您的设置应如下所示:
r.Handle(path, Adapt(theHandler, adapter1, adapter2, adapter3))
但是,既然您说您正在使用 gorilla/mux,那么您可以通过另一种方式来实现。看看Router.Use