douwen5584 2019-08-19 19:40
浏览 69
已采纳

为什么使用此适配器接口模式会出现无限循环

I need to replace an existing API interface with one that considers an incoming Auth token and also issues a machine-to-machine token for the outgoing service calls.

In summary, this is an API using gorilla/mux routing framework and I'm just adding endpoints to a mux.NewRouter(). Nothing fancy...yet ;).

I have been trying a few different patterns, but the one that seems most appealing is the Adapter Interface derived by Mat Ryer in 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

In summary with no direct logic, I have done the following and get stuck in an infinite loop when I run the endpoint from 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)))

the Adapter Interface is established as follows...

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
}

I would really appreciate knowing why this loops before I get into the details on what each adapter would be doing.

  • 写回答

1条回答 默认 最新

  • doutang7383 2019-08-19 19:54
    关注

    I think this is because your chain of handlers ends with r, in effect becoming:

    r.Handle(path, r)
    

    You have to have an actual handler somewhere to handle the call, so your setup should look like:

    r.Handle(path, Adapt(theHandler, adapter1, adapter2, adapter3))
    

    However, since you said you're using gorilla/mux, there is another way you can to this. Take a look at Router.Use

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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效