Newer
Older
// Package wsjson provides helpers for JSON messages.
package wsjson
import (
"context"
"encoding/json"
"io"
"golang.org/x/xerrors"
"nhooyr.io/websocket"
)
// Read reads a json message from c into v.
// For security reasons, it will not read messages
// larger than 32768 bytes.
func Read(ctx context.Context, c *websocket.Conn, v interface{}) error {
err := read(ctx, c, v)
if err != nil {
return xerrors.Errorf("failed to read json: %w", err)
}
return nil
}
func read(ctx context.Context, c *websocket.Conn, v interface{}) error {
typ, r, err := c.Reader(ctx)
if err != nil {
return err
}
if typ != websocket.MessageText {
c.Close(websocket.StatusUnsupportedData, "can only accept text messages")
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
return xerrors.Errorf("unexpected frame type for json (expected %v): %v", websocket.MessageText, typ)
}
r = io.LimitReader(r, 32768)
d := json.NewDecoder(r)
err = d.Decode(v)
if err != nil {
return xerrors.Errorf("failed to decode json: %w", err)
}
return nil
}
// Write writes the json message v to c.
func Write(ctx context.Context, c *websocket.Conn, v interface{}) error {
err := write(ctx, c, v)
if err != nil {
return xerrors.Errorf("failed to write json: %w", err)
}
return nil
}
func write(ctx context.Context, c *websocket.Conn, v interface{}) error {
w, err := c.Writer(ctx, websocket.MessageText)
if err != nil {
return err
}
e := json.NewEncoder(w)
err = e.Encode(v)
if err != nil {
return xerrors.Errorf("failed to encode json: %w", err)
}
err = w.Close()
if err != nil {
return err
}
return nil
}