Skip to content

Commit 6f3d9b3

Browse files
committed
Polish further
1 parent 4bfe0e9 commit 6f3d9b3

8 files changed

+239
-179
lines changed

README.md

+8-11
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55

66
websocket is a minimal and idiomatic WebSocket library for Go.
77

8-
This library is now production ready but some parts of the API are marked as experimental.
9-
10-
Please feel free to open an issue for feedback.
11-
128
## Install
139

1410
```bash
@@ -23,8 +19,8 @@ go get nhooyr.io/websocket
2319
- Thorough tests, fully passes the [autobahn-testsuite](https://github.com/crossbario/autobahn-testsuite)
2420
- Zero dependencies outside of the stdlib for the core library
2521
- JSON and ProtoBuf helpers in the wsjson and wspb subpackages
26-
- High performance, memory reuse wherever possible
27-
- Concurrent reads and writes out of the box
22+
- High performance, memory reuse by default
23+
- Concurrent writes out of the box
2824

2925
## Roadmap
3026

@@ -124,8 +120,8 @@ also uses net/http's Client and ResponseWriter directly for WebSocket handshakes
124120
gorilla/websocket writes its handshakes to the underlying net.Conn which means
125121
it has to reinvent hooks for TLS and proxies and prevents support of HTTP/2.
126122

127-
Some more advantages of nhooyr/websocket are that it supports concurrent reads,
128-
writes and makes it very easy to close the connection with a status code and reason.
123+
Some more advantages of nhooyr/websocket are that it supports concurrent writes and
124+
makes it very easy to close the connection with a status code and reason.
129125

130126
nhooyr/websocket also responds to pings, pongs and close frames in a separate goroutine so that
131127
your application doesn't always need to read from the connection unless it expects a data message.
@@ -134,11 +130,12 @@ even if you don't expect the peer to send any messages.
134130

135131
In terms of performance, the differences depend on your application code. nhooyr/websocket
136132
reuses buffers efficiently out of the box whereas gorilla/websocket does not. As mentioned
137-
above, it also supports concurrent readers and writers out of the box.
133+
above, it also supports concurrent writers out of the box.
138134

139-
The only performance downside to nhooyr/websocket is that uses two extra goroutines. One for
135+
The only performance con to nhooyr/websocket is that uses two extra goroutines. One for
140136
reading pings, pongs and close frames async to application code and another to support
141-
context.Context cancellation. This costs 4 KB of memory which is fairly cheap.
137+
context.Context cancellation. This costs 4 KB of memory which is cheap compared
138+
to the benefits.
142139

143140
### x/net/websocket
144141

accept.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ func verifyClientRequest(w http.ResponseWriter, r *http.Request) error {
7676
}
7777

7878
// Accept accepts a WebSocket handshake from a client and upgrades the
79-
// the connection to WebSocket.
79+
// the connection to a WebSocket.
8080
//
8181
// Accept will reject the handshake if the Origin domain is not the same as the Host unless
8282
// the InsecureSkipVerify option is set.
8383
//
84-
// The returned connection will be bound by r.Context(). Use c.Context() to change
84+
// The returned connection will be bound by r.Context(). Use conn.Context() to change
8585
// the bounding context.
8686
func Accept(w http.ResponseWriter, r *http.Request, opts AcceptOptions) (*Conn, error) {
8787
c, err := accept(w, r, opts)
@@ -107,15 +107,15 @@ func accept(w http.ResponseWriter, r *http.Request, opts AcceptOptions) (*Conn,
107107

108108
hj, ok := w.(http.Hijacker)
109109
if !ok {
110-
err = xerrors.New("response writer must implement http.Hijacker")
110+
err = xerrors.New("passed ResponseWriter does not implement http.Hijacker")
111111
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
112112
return nil, err
113113
}
114114

115115
w.Header().Set("Upgrade", "websocket")
116116
w.Header().Set("Connection", "Upgrade")
117117

118-
handleKey(w, r)
118+
handleSecWebSocketKey(w, r)
119119

120120
subproto := selectSubprotocol(r, opts.Subprotocols)
121121
if subproto != "" {
@@ -163,7 +163,7 @@ func selectSubprotocol(r *http.Request, subprotocols []string) string {
163163

164164
var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
165165

166-
func handleKey(w http.ResponseWriter, r *http.Request) {
166+
func handleSecWebSocketKey(w http.ResponseWriter, r *http.Request) {
167167
key := r.Header.Get("Sec-WebSocket-Key")
168168
h := sha1.New()
169169
h.Write([]byte(key))
@@ -185,5 +185,5 @@ func authenticateOrigin(r *http.Request) error {
185185
if strings.EqualFold(u.Host, r.Host) {
186186
return nil
187187
}
188-
return xerrors.Errorf("request origin %q is not authorized for host %q", origin, r.Host)
188+
return xerrors.Errorf("request Origin %q is not authorized for Host %q", origin, r.Host)
189189
}

dial.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import (
1818
// DialOptions represents the options available to pass to Dial.
1919
type DialOptions struct {
2020
// HTTPClient is the http client used for the handshake.
21-
// Its Transport must use HTTP/1.1 and return writable bodies
22-
// for WebSocket handshakes. This was introduced in Go 1.12.
23-
// http.Transport does this all correctly.
21+
// Its Transport must return writable bodies
22+
// for WebSocket handshakes.
23+
// http.Transport does this correctly beginning with Go 1.12.
2424
HTTPClient *http.Client
2525

2626
// HTTPHeader specifies the HTTP headers included in the handshake request.
@@ -30,7 +30,7 @@ type DialOptions struct {
3030
Subprotocols []string
3131
}
3232

33-
// We use this key for all client requests as the Sec-WebSocket-Key header is useless.
33+
// We use this key for all client requests as the Sec-WebSocket-Key header doesn't do anything.
3434
// See https://stackoverflow.com/a/37074398/4283659.
3535
// We also use the same mask key for every message as it too does not make a difference.
3636
var secWebSocketKey = base64.StdEncoding.EncodeToString(make([]byte, 16))
@@ -108,7 +108,7 @@ func dial(ctx context.Context, u string, opts DialOptions) (_ *Conn, _ *http.Res
108108

109109
rwc, ok := resp.Body.(io.ReadWriteCloser)
110110
if !ok {
111-
return nil, resp, xerrors.Errorf("response body is not a read write closer: %T", rwc)
111+
return nil, resp, xerrors.Errorf("response body is not a io.ReadWriteCloser: %T", rwc)
112112
}
113113

114114
c := &Conn{

example_echo_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
// dials the server and then sends 5 different messages
2121
// and prints out the server's responses.
2222
func Example_echo() {
23-
// First we listen on port 0, that means the OS will
23+
// First we listen on port 0 which means the OS will
2424
// assign us a random free port. This is the listener
2525
// the server will serve on and the client will connect to.
2626
l, err := net.Listen("tcp", "localhost:0")

messagetype.go

+2
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ const (
1313
// MessageBinary is for binary messages like Protobufs.
1414
MessageBinary MessageType = MessageType(opBinary)
1515
)
16+
17+
// Above I've explicitly included the types of the constants for stringer.

statuscode.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func parseClosePayload(p []byte) (CloseError, error) {
6060
}
6161

6262
if len(p) < 2 {
63-
return CloseError{}, xerrors.Errorf("close payload too small, cannot even contain the 2 byte status code")
63+
return CloseError{}, xerrors.Errorf("close payload %q too small, cannot even contain the 2 byte status code", p)
6464
}
6565

6666
ce := CloseError{
@@ -78,13 +78,13 @@ func parseClosePayload(p []byte) (CloseError, error) {
7878
// See http://www.iana.org/assignments/websocket/websocket.xhtml#close-code-number
7979
// and https://tools.ietf.org/html/rfc6455#section-7.4.1
8080
func validWireCloseCode(code StatusCode) bool {
81-
if code >= StatusNormalClosure && code <= statusTLSHandshake {
82-
switch code {
83-
case 1004, StatusNoStatusRcvd, statusAbnormalClosure, statusTLSHandshake:
84-
return false
85-
default:
86-
return true
87-
}
81+
switch code {
82+
case 1004, StatusNoStatusRcvd, statusAbnormalClosure, statusTLSHandshake:
83+
return false
84+
}
85+
86+
if code >= StatusNormalClosure && code <= StatusBadGateway {
87+
return true
8888
}
8989
if code >= 3000 && code <= 4999 {
9090
return true

0 commit comments

Comments
 (0)