Skip to content

Commit 8ab6030

Browse files
Steven Scottgaryburd
Steven Scott
authored andcommitted
Add JoinMessages
Fixes gorilla#441. Issue gorilla#441 specified a message separator. This PR has a message terminator. A message terminator can be read immediately following a message. A message separator cannot be read until the start of the next message. The message terminator is more useful when the reader is scanning to the terminator before performing some action.
1 parent 95ba29e commit 8ab6030

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

join.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2019 The Gorilla WebSocket Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package websocket
6+
7+
import (
8+
"io"
9+
"strings"
10+
)
11+
12+
// JoinMessages concatenates received messages to create a single io.Reader.
13+
// The string term is appended to each message. The returned reader does not
14+
// support concurrent calls to the Read method.
15+
func JoinMessages(c *Conn, term string) io.Reader {
16+
return &joinReader{c: c, term: term}
17+
}
18+
19+
type joinReader struct {
20+
c *Conn
21+
term string
22+
r io.Reader
23+
}
24+
25+
func (r *joinReader) Read(p []byte) (int, error) {
26+
if r.r == nil {
27+
var err error
28+
_, r.r, err = r.c.NextReader()
29+
if err != nil {
30+
return 0, err
31+
}
32+
if r.term != "" {
33+
r.r = io.MultiReader(r.r, strings.NewReader(r.term))
34+
}
35+
}
36+
n, err := r.r.Read(p)
37+
if err == io.EOF {
38+
err = nil
39+
r.r = nil
40+
}
41+
return n, err
42+
}

join_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2019 The Gorilla WebSocket Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package websocket
6+
7+
import (
8+
"bytes"
9+
"io"
10+
"strings"
11+
"testing"
12+
)
13+
14+
func TestJoinMessages(t *testing.T) {
15+
messages := []string{"a", "bc", "def", "ghij", "klmno", "0", "12", "345", "6789"}
16+
for _, readChunk := range []int{1, 2, 3, 4, 5, 6, 7} {
17+
for _, term := range []string{"", ","} {
18+
var connBuf bytes.Buffer
19+
wc := newTestConn(nil, &connBuf, true)
20+
rc := newTestConn(&connBuf, nil, false)
21+
for _, m := range messages {
22+
wc.WriteMessage(BinaryMessage, []byte(m))
23+
}
24+
25+
var result bytes.Buffer
26+
_, err := io.CopyBuffer(&result, JoinMessages(rc, term), make([]byte, readChunk))
27+
if IsUnexpectedCloseError(err, CloseAbnormalClosure) {
28+
t.Errorf("readChunk=%d, term=%q: unexpected error %v", readChunk, term, err)
29+
}
30+
want := strings.Join(messages, term) + term
31+
if result.String() != want {
32+
t.Errorf("readChunk=%d, term=%q, got %q, want %q", readChunk, term, result.String(), want)
33+
}
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)