local.go 2.6 KB

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