From f77d0a488faf251daedc7a49bd51a9bbbb2e58b2 Mon Sep 17 00:00:00 2001
From: Mathias Fredriksson <mafredri@gmail.com>
Date: Fri, 6 Sep 2024 13:52:49 +0000
Subject: [PATCH] docs: Fix docs and examples related to r.Context() usage

Fixes #474
---
 README.md                        | 4 +++-
 accept.go                        | 3 +++
 internal/examples/chat/chat.go   | 6 +++---
 internal/examples/echo/server.go | 6 +++---
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index 44a6ddf..80d2b3c 100644
--- a/README.md
+++ b/README.md
@@ -63,7 +63,9 @@ http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
 	}
 	defer c.CloseNow()
 
-	ctx, cancel := context.WithTimeout(r.Context(), time.Second*10)
+	// Set the context as needed. Use of r.Context() is not recommended
+	// to avoid surprising behavior (see http.Hijacker).
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
 	defer cancel()
 
 	var v interface{}
diff --git a/accept.go b/accept.go
index 68c00ed..774ea28 100644
--- a/accept.go
+++ b/accept.go
@@ -79,6 +79,9 @@ func (opts *AcceptOptions) cloneWithDefaults() *AcceptOptions {
 // See the InsecureSkipVerify and OriginPatterns options to allow cross origin requests.
 //
 // Accept will write a response to w on all errors.
+//
+// Note that using the http.Request Context after Accept returns may lead to
+// unexpected behavior (see http.Hijacker).
 func Accept(w http.ResponseWriter, r *http.Request, opts *AcceptOptions) (*Conn, error) {
 	return accept(w, r, opts)
 }
diff --git a/internal/examples/chat/chat.go b/internal/examples/chat/chat.go
index 3cb1e02..29f304b 100644
--- a/internal/examples/chat/chat.go
+++ b/internal/examples/chat/chat.go
@@ -70,7 +70,7 @@ func (cs *chatServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 // subscribeHandler accepts the WebSocket connection and then subscribes
 // it to all future messages.
 func (cs *chatServer) subscribeHandler(w http.ResponseWriter, r *http.Request) {
-	err := cs.subscribe(r.Context(), w, r)
+	err := cs.subscribe(w, r)
 	if errors.Is(err, context.Canceled) {
 		return
 	}
@@ -111,7 +111,7 @@ func (cs *chatServer) publishHandler(w http.ResponseWriter, r *http.Request) {
 //
 // It uses CloseRead to keep reading from the connection to process control
 // messages and cancel the context if the connection drops.
-func (cs *chatServer) subscribe(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
+func (cs *chatServer) subscribe(w http.ResponseWriter, r *http.Request) error {
 	var mu sync.Mutex
 	var c *websocket.Conn
 	var closed bool
@@ -142,7 +142,7 @@ func (cs *chatServer) subscribe(ctx context.Context, w http.ResponseWriter, r *h
 	mu.Unlock()
 	defer c.CloseNow()
 
-	ctx = c.CloseRead(ctx)
+	ctx := c.CloseRead(context.Background())
 
 	for {
 		select {
diff --git a/internal/examples/echo/server.go b/internal/examples/echo/server.go
index a44d20b..37e2f2c 100644
--- a/internal/examples/echo/server.go
+++ b/internal/examples/echo/server.go
@@ -37,7 +37,7 @@ func (s echoServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 
 	l := rate.NewLimiter(rate.Every(time.Millisecond*100), 10)
 	for {
-		err = echo(r.Context(), c, l)
+		err = echo(c, l)
 		if websocket.CloseStatus(err) == websocket.StatusNormalClosure {
 			return
 		}
@@ -51,8 +51,8 @@ func (s echoServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 // echo reads from the WebSocket connection and then writes
 // the received message back to it.
 // The entire function has 10s to complete.
-func echo(ctx context.Context, c *websocket.Conn, l *rate.Limiter) error {
-	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
+func echo(c *websocket.Conn, l *rate.Limiter) error {
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
 	defer cancel()
 
 	err := l.Wait(ctx)
-- 
GitLab