github.com/rhatdan/docker@v0.7.7-0.20180119204836-47a0dcbcd20a/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  }