github.com/cookieai-jar/moby@v17.12.1-ce-rc2+incompatible/api/server/router/local.go (about) 1 package router 2 3 import ( 4 "net/http" 5 6 "github.com/docker/docker/api/server/httputils" 7 "golang.org/x/net/context" 8 ) 9 10 // RouteWrapper wraps a route with extra functionality. 11 // It is passed in when creating a new route. 12 type RouteWrapper func(r Route) Route 13 14 // localRoute defines an individual API route to connect 15 // with the docker daemon. It implements Route. 16 type localRoute struct { 17 method string 18 path string 19 handler httputils.APIFunc 20 } 21 22 // Handler returns the APIFunc to let the server wrap it in middlewares. 23 func (l localRoute) Handler() httputils.APIFunc { 24 return l.handler 25 } 26 27 // Method returns the http method that the route responds to. 28 func (l localRoute) Method() string { 29 return l.method 30 } 31 32 // Path returns the subpath where the route responds to. 33 func (l localRoute) Path() string { 34 return l.path 35 } 36 37 // NewRoute initializes a new local route for the router. 38 func NewRoute(method, path string, handler httputils.APIFunc, opts ...RouteWrapper) Route { 39 var r Route = localRoute{method, path, handler} 40 for _, o := range opts { 41 r = o(r) 42 } 43 return r 44 } 45 46 // NewGetRoute initializes a new route with the http method GET. 47 func NewGetRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route { 48 return NewRoute("GET", path, handler, opts...) 49 } 50 51 // NewPostRoute initializes a new route with the http method POST. 52 func NewPostRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route { 53 return NewRoute("POST", path, handler, opts...) 54 } 55 56 // NewPutRoute initializes a new route with the http method PUT. 57 func NewPutRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route { 58 return NewRoute("PUT", path, handler, opts...) 59 } 60 61 // NewDeleteRoute initializes a new route with the http method DELETE. 62 func NewDeleteRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route { 63 return NewRoute("DELETE", path, handler, opts...) 64 } 65 66 // NewOptionsRoute initializes a new route with the http method OPTIONS. 67 func NewOptionsRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route { 68 return NewRoute("OPTIONS", path, handler, opts...) 69 } 70 71 // NewHeadRoute initializes a new route with the http method HEAD. 72 func NewHeadRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route { 73 return NewRoute("HEAD", path, handler, opts...) 74 } 75 76 func cancellableHandler(h httputils.APIFunc) httputils.APIFunc { 77 return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 78 if notifier, ok := w.(http.CloseNotifier); ok { 79 notify := notifier.CloseNotify() 80 notifyCtx, cancel := context.WithCancel(ctx) 81 finished := make(chan struct{}) 82 defer close(finished) 83 ctx = notifyCtx 84 go func() { 85 select { 86 case <-notify: 87 cancel() 88 case <-finished: 89 } 90 }() 91 } 92 return h(ctx, w, r, vars) 93 } 94 } 95 96 // WithCancel makes new route which embeds http.CloseNotifier feature to 97 // context.Context of handler. 98 func WithCancel(r Route) Route { 99 return localRoute{ 100 method: r.Method(), 101 path: r.Path(), 102 handler: cancellableHandler(r.Handler()), 103 } 104 }