Closed
Description
Everywhere we got an error when read from / write into underlying transport (incl. flush write buffer), we should check if we have closed the connection, and wrap a CloseError.
How to reproduce
package main
import (
"context"
"log"
"net/http"
"net/http/httptest"
"strings"
"time"
"nhooyr.io/websocket"
)
func handleHTTP(w http.ResponseWriter, r *http.Request) {
ws, err := websocket.Accept(w, r, nil)
if err == nil {
go handleWS(ws)
}
}
func handleWS(conn *websocket.Conn) {
defer conn.Close(websocket.StatusInternalError, "oops")
ctx := context.Background()
for {
_, _, err := conn.Read(ctx)
if err != nil {
return
}
}
}
func main() {
ctx := context.Background()
server := httptest.NewServer(http.HandlerFunc(handleHTTP))
defer server.Close()
url := strings.Replace(server.URL, "http", "ws", 1)
client, _, _ := websocket.Dial(ctx, url, nil)
// write something in background
joinCh := make(chan struct{})
go func() {
defer close(joinCh)
for {
err := client.Write(ctx, websocket.MessageText, []byte("test"))
if err != nil {
log.Print("client write error: ", err)
log.Print("client close status code: ", websocket.CloseStatus(err))
return
}
}
}()
// close after some time
time.Sleep(time.Millisecond)
_ = client.Close(websocket.StatusNormalClosure, "bye")
<- joinCh
}
Expected output
2020/03/15 21:20:23 client write error: failed to write msg: failed to close writer: failed to write fin frame: failed to write frame: WebSocket closed: sent close frame: status = StatusNormalClosure and reason = "bye"
2020/03/15 21:20:23 client close status code: StatusNormalClosure
Unexpected output
2020/03/15 21:20:21 client write error: failed to write msg: failed to close writer: failed to write fin frame: failed to write frame: failed to flush: write tcp 127.0.0.1:59943->127.0.0.1:59942: use of closed network connection
2020/03/15 21:20:21 client close status code: StatusCode(-1)
Metadata
Metadata
Assignees
Labels
No labels