// APIServerHandlers holds the different http.Handlers used by the API server.
// This includes the full handler chain, the director (which chooses between gorestful and nonGoRestful,
// the gorestful handler (used for the API) which falls through to the nonGoRestful handler on unregistered paths,
// and the nonGoRestful handler (which can contain a fallthrough of its own)
// FullHandlerChain -> Director -> {GoRestfulContainer,NonGoRestfulMux} based on inspection of registered web services
type APIServerHandler struct {
// FullHandlerChain is the one that is eventually served with. It should include the full filter
// chain and then call the Director.
FullHandlerChain http.Handler
// The registered APIs. InstallAPIs uses this. Other servers probably shouldn't access this directly.
GoRestfulContainer *restful.Container
// NonGoRestfulMux is the final HTTP handler in the chain.
// It comes after all filters and the API handling
// This is where other servers can attach handler to various parts of the chain.
NonGoRestfulMux *mux.PathRecorderMux
// Director is here so that we can properly handle fall through and proxy cases.
// This looks a bit bonkers, but here's what's happening. We need to have /apis handling registered in gorestful in order to have
// swagger generated for compatibility. Doing that with `/apis` as a webservice, means that it forcibly 404s (no defaulting allowed)
// all requests which are not /apis or /apis/. We need those calls to fall through behind goresful for proper delegation. Trying to
// register for a pattern which includes everything behind it doesn't work because gorestful negotiates for verbs and content encoding
// and all those things go crazy when gorestful really just needs to pass through. In addition, openapi enforces unique verb constraints
// which we don't fit into and it still muddies up swagger. Trying to switch the webservices into a route doesn't work because the
// containing webservice faces all the same problems listed above.
// This leads to the crazy thing done here. Our mux does what we need, so we'll place it in front of gorestful. It will introspect to
// decide if the route is likely to be handled by goresful and route there if needed. Otherwise, it goes to PostGoRestful mux in
// order to handle "normal" paths and delegation. Hopefully no API consumers will ever have to deal with this level of detail. I think
// we should consider completely removing gorestful.
// Other servers should only use this opaquely to delegate to an API server.
Director http.Handler
}
func NewAPIServerHandler(name string, s runtime.NegotiatedSerializer, handlerChainBuilder HandlerChainBuilderFn, notFoundHandler http.Handler) *APIServerHandler {
nonGoRestfulMux := mux.NewPathRecorderMux(name)
if notFoundHandler != nil {
nonGoRestfulMux.NotFoundHandler(notFoundHandler)
}
gorestfulContainer := restful.NewContainer()
director := director{
name: name,
goRestfulContainer: gorestfulContainer,
nonGoRestfulMux: nonGoRestfulMux,
}
return &APIServerHandler{
FullHandlerChain: handlerChainBuilder(director),
GoRestfulContainer: gorestfulContainer,
NonGoRestfulMux: nonGoRestfulMux,
Director: director,
}
}
type director struct {
name string
goRestfulContainer *restful.Container
nonGoRestfulMux *mux.PathRecorderMux
}
大家都知道APIService是有三部分组成的,APIAggregator, APIServer 和APIExtension。 它们是通过一个delegateChain串联起来了。但是具体怎么实现的呢。并没有很多文章说的很详细。包括源码剖析中。由于这部分涉及的代码块比较多,来回切换看,不太容易记得。所以导致不太好理解。
经过在微信群里面请教,基本上算是里明白啦,在这里记录一下,可以方便有同困惑的同学们可以参考,以共同学习进步!
我有下面两个困惑:
对于FullHandlerChain和Director比较好理解,FullHandlerChain就是将director进行了一层filterHandler的封装。而Director更直接,从代码中看到,它就是根据不同的name存储了对应的goRestful的API指针和nonGoRestful的API的指针,为了后面可以使用。 而这里的APIServerHandler中的GoRestfulContainer和NonGoRestfulMux,我是不太明白为啥要暴露出来。不过从注释上来看,它只是在installAPI的时候要把API都添加进去。然后Director由于存的是他们的指针,所以Director中对应的API也都有了,因此后面再APIChain的调用中,调用Director就能处理到这些API了。所以我的理解可能是不想直接操作Director这个结构吧。毕竟它是一个interface 指向了director 这个结构。
通过源码的分析,总结出下面这个调用流图可供参考:
这里就是当你调用一个API的时候,就会按照这个处理流程去处理。首先就是filterHandler,这个是一些筛选handler,包括认证授权等。后面就是三种server的调用链了。
最后,如果你有同样的问题,希望可以帮到你!
如果大牛们对我的分析和理解有误。还请指出!