Skip to content

Commit 9213cc7

Browse files
committed
Significantly simplify core API and the godoc
1 parent 0e78812 commit 9213cc7

File tree

4 files changed

+26
-60
lines changed

4 files changed

+26
-60
lines changed

example_test.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,9 @@ func ExampleAccept_echo() {
3434
return err
3535
}
3636

37-
ctx, cancel = context.WithTimeout(ctx, time.Second*10)
38-
defer cancel()
39-
40-
r.SetContext(ctx)
41-
r.Limit(32768)
37+
r = io.LimitReader(r, 32768)
4238

43-
w := c.MessageWriter(typ)
44-
w.SetContext(ctx)
39+
w := c.MessageWriter(ctx, typ)
4540
_, err = io.Copy(w, r)
4641
if err != nil {
4742
return err

json.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package websocket
33
import (
44
"context"
55
"encoding/json"
6+
"io"
67

78
"golang.org/x/xerrors"
89
)
@@ -31,8 +32,7 @@ func (jc *JSONConn) read(ctx context.Context, v interface{}) error {
3132
return xerrors.Errorf("unexpected frame type for json (expected DataText): %v", typ)
3233
}
3334

34-
r.Limit(131072)
35-
r.SetContext(ctx)
35+
r = io.LimitReader(r, 131072)
3636

3737
d := json.NewDecoder(r)
3838
err = d.Decode(v)
@@ -52,8 +52,7 @@ func (jc JSONConn) Write(ctx context.Context, v interface{}) error {
5252
}
5353

5454
func (jc JSONConn) write(ctx context.Context, v interface{}) error {
55-
w := jc.Conn.MessageWriter(DataText)
56-
w.SetContext(ctx)
55+
w := jc.Conn.MessageWriter(ctx, DataText)
5756

5857
e := json.NewEncoder(w)
5958
err := e.Encode(v)

websocket.go

Lines changed: 20 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -403,19 +403,19 @@ func (c *Conn) writeControl(ctx context.Context, opcode opcode, p []byte) error
403403

404404
// MessageWriter returns a writer bounded by the context that will write
405405
// a WebSocket data frame of type dataType to the connection.
406-
// Ensure you close the MessageWriter once you have written to entire message.
407-
// Concurrent calls to MessageWriter are ok.
408-
func (c *Conn) MessageWriter(dataType DataType) *MessageWriter {
409-
return &MessageWriter{
406+
// Ensure you close the messageWriter once you have written to entire message.
407+
// Concurrent calls to messageWriter are ok.
408+
func (c *Conn) MessageWriter(ctx context.Context, dataType DataType) io.WriteCloser {
409+
return &messageWriter{
410410
c: c,
411-
ctx: context.Background(),
411+
ctx: ctx,
412412
datatype: dataType,
413413
}
414414
}
415415

416-
// MessageWriter enables writing to a WebSocket connection.
417-
// Ensure you close the MessageWriter once you have written to entire message.
418-
type MessageWriter struct {
416+
// messageWriter enables writing to a WebSocket connection.
417+
// Ensure you close the messageWriter once you have written to entire message.
418+
type messageWriter struct {
419419
datatype DataType
420420
ctx context.Context
421421
c *Conn
@@ -429,7 +429,7 @@ type MessageWriter struct {
429429
// The frame will automatically be fragmented as appropriate
430430
// with the buffers obtained from http.Hijacker.
431431
// Please ensure you call Close once you have written the full message.
432-
func (w *MessageWriter) Write(p []byte) (int, error) {
432+
func (w *messageWriter) Write(p []byte) (int, error) {
433433
if !w.acquiredLock {
434434
select {
435435
case <-w.c.closed:
@@ -458,14 +458,9 @@ func (w *MessageWriter) Write(p []byte) (int, error) {
458458
}
459459
}
460460

461-
// SetContext bounds the writer to the context.
462-
func (w *MessageWriter) SetContext(ctx context.Context) {
463-
w.ctx = ctx
464-
}
465-
466461
// Close flushes the frame to the connection.
467-
// This must be called for every MessageWriter.
468-
func (w *MessageWriter) Close() error {
462+
// This must be called for every messageWriter.
463+
func (w *messageWriter) Close() error {
469464
if !w.acquiredLock {
470465
select {
471466
case <-w.c.closed:
@@ -492,50 +487,35 @@ func (w *MessageWriter) Close() error {
492487
// Please use SetContext on the reader to bound the read operation.
493488
// Your application must keep reading messages for the Conn to automatically respond to ping
494489
// and close frames.
495-
func (c *Conn) ReadMessage(ctx context.Context) (DataType, *MessageReader, error) {
490+
func (c *Conn) ReadMessage(ctx context.Context) (DataType, io.Reader, error) {
496491
select {
497492
case <-c.closed:
498493
return 0, nil, xerrors.Errorf("failed to read message: %w", c.getCloseErr())
499494
case opcode := <-c.read:
500-
return DataType(opcode), &MessageReader{
501-
ctx: context.Background(),
495+
return DataType(opcode), &messageReader{
496+
ctx: ctx,
502497
c: c,
503498
}, nil
504499
case <-ctx.Done():
505500
return 0, nil, xerrors.Errorf("failed to read message: %w", ctx.Err())
506501
}
507502
}
508503

509-
// MessageReader enables reading a data frame from the WebSocket connection.
510-
type MessageReader struct {
511-
n int
512-
limit int
513-
c *Conn
514-
ctx context.Context
504+
// messageReader enables reading a data frame from the WebSocket connection.
505+
type messageReader struct {
506+
ctx context.Context
507+
c *Conn
515508
}
516509

517510
// SetContext bounds the read operation to the ctx.
518511
// By default, the context is the one passed to conn.ReadMessage.
519512
// You still almost always want a separate context for reading the message though.
520-
func (r *MessageReader) SetContext(ctx context.Context) {
513+
func (r *messageReader) SetContext(ctx context.Context) {
521514
r.ctx = ctx
522515
}
523516

524-
// Limit limits the number of bytes read by the reader.
525-
//
526-
// Why not use io.LimitReader? io.LimitReader returns a io.EOF
527-
// after the limit bytes which means its not possible to tell
528-
// whether the message has been read or a limit has been hit.
529-
// This results in unclear error and log messages.
530-
// This function will cause the connection to be closed if the limit is hit
531-
// with a close reason explaining the error and also an error
532-
// indicating the limit was hit.
533-
func (r *MessageReader) Limit(bytes int) {
534-
r.limit = bytes
535-
}
536-
537517
// Read reads as many bytes as possible into p.
538-
func (r *MessageReader) Read(p []byte) (n int, err error) {
518+
func (r *messageReader) Read(p []byte) (n int, err error) {
539519
select {
540520
case <-r.c.closed:
541521
return 0, r.c.getCloseErr()
@@ -546,11 +526,6 @@ func (r *MessageReader) Read(p []byte) (n int, err error) {
546526
case <-r.c.closed:
547527
return 0, r.c.getCloseErr()
548528
case n := <-r.c.readDone:
549-
r.n += n
550-
// TODO make this better later and inside readLoop to prevent the read from actually occuring if over limit.
551-
if r.limit > 0 && r.n > r.limit {
552-
return 0, xerrors.New("message too big")
553-
}
554529
return n, nil
555530
case <-r.ctx.Done():
556531
return 0, r.ctx.Err()

websocket_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,7 @@ func echoLoop(ctx context.Context, c *websocket.Conn, t *testing.T) {
365365
return err
366366
}
367367

368-
r.SetContext(ctx)
369-
370-
w := c.MessageWriter(typ)
371-
w.SetContext(ctx)
368+
w := c.MessageWriter(ctx, typ)
372369

373370
_, err = io.Copy(w, r)
374371
if err != nil {

0 commit comments

Comments
 (0)