2015-12-30 12:20:41 -05:00
|
|
|
package router
|
|
|
|
|
2016-03-23 13:01:34 -04:00
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"github.com/docker/docker/api/server/httputils"
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
)
|
2015-12-30 12:20:41 -05:00
|
|
|
|
2017-04-10 21:14:36 -04:00
|
|
|
// RouteWrapper wraps a route with extra functionality.
|
|
|
|
// It is passed in when creating a new route.
|
|
|
|
type RouteWrapper func(r Route) Route
|
|
|
|
|
2015-12-30 12:20:41 -05:00
|
|
|
// localRoute defines an individual API route to connect
|
|
|
|
// with the docker daemon. It implements Route.
|
|
|
|
type localRoute struct {
|
|
|
|
method string
|
|
|
|
path string
|
|
|
|
handler httputils.APIFunc
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handler returns the APIFunc to let the server wrap it in middlewares.
|
|
|
|
func (l localRoute) Handler() httputils.APIFunc {
|
|
|
|
return l.handler
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method returns the http method that the route responds to.
|
|
|
|
func (l localRoute) Method() string {
|
|
|
|
return l.method
|
|
|
|
}
|
|
|
|
|
|
|
|
// Path returns the subpath where the route responds to.
|
|
|
|
func (l localRoute) Path() string {
|
|
|
|
return l.path
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewRoute initializes a new local route for the router.
|
2017-04-10 21:14:36 -04:00
|
|
|
func NewRoute(method, path string, handler httputils.APIFunc, opts ...RouteWrapper) Route {
|
|
|
|
var r Route = localRoute{method, path, handler}
|
|
|
|
for _, o := range opts {
|
|
|
|
r = o(r)
|
|
|
|
}
|
|
|
|
return r
|
2015-12-30 12:20:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewGetRoute initializes a new route with the http method GET.
|
2017-04-10 21:14:36 -04:00
|
|
|
func NewGetRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route {
|
|
|
|
return NewRoute("GET", path, handler, opts...)
|
2015-12-30 12:20:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewPostRoute initializes a new route with the http method POST.
|
2017-04-10 21:14:36 -04:00
|
|
|
func NewPostRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route {
|
|
|
|
return NewRoute("POST", path, handler, opts...)
|
2015-12-30 12:20:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewPutRoute initializes a new route with the http method PUT.
|
2017-04-10 21:14:36 -04:00
|
|
|
func NewPutRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route {
|
|
|
|
return NewRoute("PUT", path, handler, opts...)
|
2015-12-30 12:20:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewDeleteRoute initializes a new route with the http method DELETE.
|
2017-04-10 21:14:36 -04:00
|
|
|
func NewDeleteRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route {
|
|
|
|
return NewRoute("DELETE", path, handler, opts...)
|
2015-12-30 12:20:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewOptionsRoute initializes a new route with the http method OPTIONS.
|
2017-04-10 21:14:36 -04:00
|
|
|
func NewOptionsRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route {
|
|
|
|
return NewRoute("OPTIONS", path, handler, opts...)
|
2015-12-30 12:20:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewHeadRoute initializes a new route with the http method HEAD.
|
2017-04-10 21:14:36 -04:00
|
|
|
func NewHeadRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route {
|
|
|
|
return NewRoute("HEAD", path, handler, opts...)
|
2015-12-30 12:20:41 -05:00
|
|
|
}
|
2016-03-23 13:01:34 -04:00
|
|
|
|
|
|
|
func cancellableHandler(h httputils.APIFunc) httputils.APIFunc {
|
|
|
|
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
|
|
if notifier, ok := w.(http.CloseNotifier); ok {
|
|
|
|
notify := notifier.CloseNotify()
|
|
|
|
notifyCtx, cancel := context.WithCancel(ctx)
|
|
|
|
finished := make(chan struct{})
|
|
|
|
defer close(finished)
|
|
|
|
ctx = notifyCtx
|
|
|
|
go func() {
|
|
|
|
select {
|
|
|
|
case <-notify:
|
|
|
|
cancel()
|
|
|
|
case <-finished:
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
return h(ctx, w, r, vars)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-10 21:14:36 -04:00
|
|
|
// WithCancel makes new route which embeds http.CloseNotifier feature to
|
2016-03-23 13:01:34 -04:00
|
|
|
// context.Context of handler.
|
2017-04-10 21:14:36 -04:00
|
|
|
func WithCancel(r Route) Route {
|
2016-03-23 13:01:34 -04:00
|
|
|
return localRoute{
|
|
|
|
method: r.Method(),
|
|
|
|
path: r.Path(),
|
|
|
|
handler: cancellableHandler(r.Handler()),
|
|
|
|
}
|
|
|
|
}
|