为什么我会得到这个适配器接口模式的无限循环

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

https://godoc.org/github.com/gorilla/mux#Router.Use