local.go 3.0 KB

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