websocket
websocket copied to clipboard
Compressed messages fail in Safari
When Safari 13.1 for MacOS receives a compressed text message, it prints WebSocket connection to 'ws://localhost:8080/ws' failed: Could not decode a text frame as UTF-8
on the Javascript console and closes the WebSocket connection.
This is probably a bug in Safari. But this issue might help others to disable compression as a workaround. They have to pass AcceptOptions
to Accept()
:
websocket.AcceptOptions{
CompressionMode: websocket.CompressionDisabled,
}
Received an email report about this as well, will look into it.
For now you can disable compression.
Might be https://bugs.webkit.org/show_bug.cgi?id=202401 as reported in the email I got.
Please let me know if this occurs on messages smaller than 4092 bytes.
Yes, this also occurs with much smaller messages. A message with 186 bytes uncompressed size already causes the error. Messages with 30-40 bytes work well - maybe because they won't be compressed?
Hmm, weird. Could you try the technology preview and see if that fixes it as the patches landed in Safari several months ago.
Hmm actually fixes should be in 13.1 as it released just a week ago.
Best to just disable compression for now until I figure out what's going on here.
To clarify I mean I'm going to turn off compression by default.
Confirmed reproduction btw with the new chat example. It's proven handy already.
@nhooyr we are facing a similar issue with Safari version 15.1 (17612.2.9.1.20)
in Monterey
OS if compression is enabled
wsc, err := websocket.Accept(c.Response(), c.Request(), &websocket.AcceptOptions{
CompressionMode: websocket.CompressionContextTakeover,
InsecureSkipVerify: true,
})
We get below error is mentioned Safari,
The operation couldn’t be completed. (kNWErrorDomainPOSIX error 100 - Protocol error)
If we disable compression, it works fine. Is there any suggestion for using it with compression enabled?
Now safari are using x-webkit-deflate-frame
instead of permessage-deflate
, so just comment case: x-webkit-deflate-frame
is not working now.
I'm suffering this issue only under k8s + istio + gin. While running the same code on my macbook, this problem disappeared.
The log shows the error comes from deeply in frame.go
-> readFrameHeader
at line 51, as EOF
.
Is there a way to mirror the c.Request.Body
reader to a buffer, so that I can log more about what exactly data have been read
/reopen
Sorry I don't currently have the time to help debug, in the middle of closing a home, working a new job and moving.
But I've reopened this issue to investigate at some future date.
You can disable this conditionally only for Safari:
acceptOptions := &websocket.AcceptOptions{
// ...
}
userAgentLower := strings.ToLower(r.Header.Get("User-Agent"))
isSafari := strings.Contains(userAgentLower, "safari") && !strings.Contains(userAgentLower, "chrome") && !strings.Contains(userAgentLower, "android")
if isSafari {
acceptOptions.CompressionMode = websocket.CompressionDisabled
}
conn, err := websocket.Accept(w, r, acceptOptions)
See: https://github.com/poki/netlib/pull/28
I would suggest not using compression at all. It's proven too unreliable even without Safari. See #391
Will be disabled by default in #256
Going to close as the commit in dev exists to disable it.