Преглед на файлове

api/server/router: add Cancellable function

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
Alexander Morozov преди 9 години
родител
ревизия
bdd9388c42
променени са 1 файла, в които са добавени 36 реда и са изтрити 1 реда
  1. 36 1
      api/server/router/local.go

+ 36 - 1
api/server/router/local.go

@@ -1,6 +1,11 @@
 package router
 
-import "github.com/docker/docker/api/server/httputils"
+import (
+	"net/http"
+
+	"github.com/docker/docker/api/server/httputils"
+	"golang.org/x/net/context"
+)
 
 // localRoute defines an individual API route to connect
 // with the docker daemon. It implements Route.
@@ -59,3 +64,33 @@ func NewOptionsRoute(path string, handler httputils.APIFunc) Route {
 func NewHeadRoute(path string, handler httputils.APIFunc) Route {
 	return NewRoute("HEAD", path, handler)
 }
+
+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)
+	}
+}
+
+// Cancellable makes new route which embeds http.CloseNotifier feature to
+// context.Context of handler.
+func Cancellable(r Route) Route {
+	return localRoute{
+		method:  r.Method(),
+		path:    r.Path(),
+		handler: cancellableHandler(r.Handler()),
+	}
+}