Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitca133c8

Browse files
committed
fix: ensure websocket close messages are truncated to 123 bytes
It's possible for websocket close messages to be too long, which causethem to silently fail without a proper close message. See error below:```2022-03-31 17:08:34.862 [INFO](stdlib)<close_notjs.go:72>"2022/03/31 17:08:34 websocket: failed to marshal close frame: reason string max is 123 but got \"insert provisioner daemon:Cannot encode []database.ProvisionerType into oid 19098 - []database.ProvisionerType must implement Encoder or be converted to a string\" with length 161"```
1 parentbb6c12d commitca133c8

File tree

4 files changed

+73
-5
lines changed

4 files changed

+73
-5
lines changed

‎coderd/provisionerdaemons.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func (api *api) provisionerDaemonsListen(rw http.ResponseWriter, r *http.Request
5656
Provisioners: []database.ProvisionerType{database.ProvisionerTypeEcho,database.ProvisionerTypeTerraform},
5757
})
5858
iferr!=nil {
59-
_=conn.Close(websocket.StatusInternalError,fmt.Sprintf("insert provisioner daemon:%s",err))
59+
_=conn.Close(websocket.StatusInternalError,fmtWebsocketCloseMsg("insert provisioner daemon: %s",err))
6060
return
6161
}
6262

@@ -67,7 +67,7 @@ func (api *api) provisionerDaemonsListen(rw http.ResponseWriter, r *http.Request
6767
config.LogOutput=io.Discard
6868
session,err:=yamux.Server(websocket.NetConn(r.Context(),conn,websocket.MessageBinary),config)
6969
iferr!=nil {
70-
_=conn.Close(websocket.StatusInternalError,fmt.Sprintf("multiplex server: %s",err))
70+
_=conn.Close(websocket.StatusInternalError,fmtWebsocketCloseMsg("multiplex server: %s",err))
7171
return
7272
}
7373
mux:=drpcmux.New()
@@ -80,13 +80,13 @@ func (api *api) provisionerDaemonsListen(rw http.ResponseWriter, r *http.Request
8080
Logger:api.Logger.Named(fmt.Sprintf("provisionerd-%s",daemon.Name)),
8181
})
8282
iferr!=nil {
83-
_=conn.Close(websocket.StatusInternalError,fmt.Sprintf("drpc register provisioner daemon: %s",err))
83+
_=conn.Close(websocket.StatusInternalError,fmtWebsocketCloseMsg("drpc register provisioner daemon: %s",err))
8484
return
8585
}
8686
server:=drpcserver.New(mux)
8787
err=server.Serve(r.Context(),session)
8888
iferr!=nil {
89-
_=conn.Close(websocket.StatusInternalError,fmt.Sprintf("serve: %s",err))
89+
_=conn.Close(websocket.StatusInternalError,fmtWebsocketCloseMsg("serve: %s",err))
9090
return
9191
}
9292
_=conn.Close(websocket.StatusGoingAway,"")

‎coderd/workspaceresources.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func (api *api) workspaceResourceDial(rw http.ResponseWriter, r *http.Request) {
108108
Pubsub:api.Pubsub,
109109
})
110110
iferr!=nil {
111-
_=conn.Close(websocket.StatusInternalError,fmt.Sprintf("serve: %s",err))
111+
_=conn.Close(websocket.StatusInternalError,fmtWebsocketCloseMsg("serve: %s",err))
112112
return
113113
}
114114
}

‎coderd/ws.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package coderd
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
constwebsocketCloseMaxLen=123
9+
10+
// fmtWebsocketCloseMsg formats a websocket close message and ensures it is
11+
// truncated to the maximum allowed length.
12+
funcfmtWebsocketCloseMsg(formatstring,vars...any)string {
13+
msg:=fmt.Sprintf(format,vars...)
14+
15+
// Cap msg length at 123 bytes. nhooyr/websocket only allows close messages
16+
// of this length.
17+
iflen(msg)>websocketCloseMaxLen {
18+
returntruncateString(msg,websocketCloseMaxLen)
19+
}
20+
21+
returnmsg
22+
}
23+
24+
// truncateString safely truncates a string to a maximum size of byteLen. It
25+
// writes whole runes until a single rune would increase the string size above
26+
// byteLen.
27+
functruncateString(strstring,byteLenint)string {
28+
sb:= strings.Builder{}
29+
sb.Grow(byteLen)
30+
31+
for_,char:=rangestr {
32+
ifsb.Len()+len(string(char))>byteLen {
33+
break
34+
}
35+
36+
sb.WriteRune(char)
37+
}
38+
39+
returnsb.String()
40+
}

‎coderd/ws_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package coderd
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
funcTest_websocketCloseMsg(t*testing.T) {
11+
t.Parallel()
12+
13+
t.Run("TruncateSingleByteCharacters",func(t*testing.T) {
14+
t.Parallel()
15+
16+
msg:=strings.Repeat("d",255)
17+
trunc:=fmtWebsocketCloseMsg(msg)
18+
assert.LessOrEqual(t,len(trunc),123)
19+
})
20+
21+
t.Run("TruncateMultiByteCharacters",func(t*testing.T) {
22+
t.Parallel()
23+
24+
msg:=strings.Repeat("こんにちは",10)
25+
trunc:=fmtWebsocketCloseMsg(msg)
26+
assert.LessOrEqual(t,len(trunc),123)
27+
})
28+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp