Documentation ¶
Overview ¶
Example (CrossOrigin) ¶
package main import ( "log" "net/http" "github.com/switchupcb/websocket" ) func main() { // This handler demonstrates how to safely accept cross origin WebSockets // from the origin example.com. fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { c, err := websocket.Accept(w, r, &websocket.AcceptOptions{ OriginPatterns: []string{"example.com"}, }) if err != nil { log.Println(err) return } c.Close(websocket.StatusNormalClosure, "cross origin WebSocket accepted") }) err := http.ListenAndServe("localhost:8080", fn) log.Fatal(err) }
Output:
Example (Echo) ¶
This example demonstrates a echo server.
package main import () func main() { // https://github.com/nhooyr/websocket/tree/master/examples/echo }
Output:
Example (FullStackChat) ¶
This example demonstrates full stack chat with an automated test.
package main import () func main() { // https://github.com/nhooyr/websocket/tree/master/examples/chat }
Output:
Example (WriteOnly) ¶
package main import ( "context" "log" "net/http" "time" "github.com/switchupcb/websocket" "github.com/switchupcb/websocket/wsjson" ) func main() { // This handler demonstrates how to correctly handle a write only WebSocket connection. // i.e you only expect to write messages and do not expect to read any messages. fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { c, err := websocket.Accept(w, r, nil) if err != nil { log.Println(err) return } defer c.Close(websocket.StatusInternalError, "the sky is falling") ctx, cancel := context.WithTimeout(r.Context(), time.Minute*10) defer cancel() ctx = c.CloseRead(ctx) t := time.NewTicker(time.Second * 30) defer t.Stop() for { select { case <-ctx.Done(): c.Close(websocket.StatusNormalClosure, "") return case <-t.C: err = wsjson.Write(ctx, c, "hi") if err != nil { log.Println(err) return } } } }) err := http.ListenAndServe("localhost:8080", fn) log.Fatal(err) }
Output:
Index ¶
- func NetConn(ctx context.Context, c *Conn, msgType MessageType) net.Conn
- type AcceptOptions
- type CloseError
- type CompressionMode
- type Conn
- func (c *Conn) Close(code StatusCode, reason string) error
- func (c *Conn) CloseRead(ctx context.Context) context.Context
- func (c *Conn) Ping(ctx context.Context) error
- func (c *Conn) Read(ctx context.Context) (MessageType, []byte, error)
- func (c *Conn) Reader(ctx context.Context) (MessageType, io.Reader, error)
- func (c *Conn) SetReadLimit(n int64)
- func (c *Conn) Subprotocol() string
- func (c *Conn) Write(ctx context.Context, typ MessageType, p []byte) error
- func (c *Conn) Writer(ctx context.Context, typ MessageType) (io.WriteCloser, error)
- type DialOptions
- type MessageType
- type StatusCode
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NetConn ¶
NetConn converts a *websocket.Conn into a net.Conn.
It's for tunneling arbitrary protocols over WebSockets. Few users of the library will need this but it's tricky to implement correctly and so provided in the library. See https://github.com/nhooyr/websocket/issues/100.
Every Write to the net.Conn will correspond to a message write of the given type on *websocket.Conn.
The passed ctx bounds the lifetime of the net.Conn. If cancelled, all reads and writes on the net.Conn will be cancelled.
If a message is read that is not of the correct type, the connection will be closed with StatusUnsupportedData and an error will be returned.
Close will close the *websocket.Conn with StatusNormalClosure.
When a deadline is hit, the connection will be closed. This is different from most net.Conn implementations where only the reading/writing goroutines are interrupted but the connection is kept alive.
The Addr methods will return a mock net.Addr that returns "websocket" for Network and "websocket/unknown-addr" for String.
A received StatusNormalClosure or StatusGoingAway close frame will be translated to io.EOF when reading.
Types ¶
type AcceptOptions ¶
type AcceptOptions struct { Subprotocols []string InsecureSkipVerify bool OriginPatterns []string CompressionMode CompressionMode CompressionThreshold int }
AcceptOptions represents Accept's options.
type CloseError ¶
type CloseError struct { Code StatusCode Reason string }
CloseError is returned when the connection is closed with a status and reason.
Use Go 1.13's errors.As to check for this error. Also see the CloseStatus helper.
func (CloseError) Error ¶
func (ce CloseError) Error() string
type CompressionMode ¶
type CompressionMode int
CompressionMode represents the modes available to the deflate extension. See https://tools.ietf.org/html/rfc7692
A compatibility layer is implemented for the older deflate-frame extension used by safari. See https://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate-06 It will work the same in every way except that we cannot signal to the peer we want to use no context takeover on our side, we can only signal that they should. It is however currently disabled due to Safari bugs. See https://github.com/nhooyr/websocket/issues/218
const ( // CompressionNoContextTakeover grabs a new flate.Reader and flate.Writer as needed // for every message. This applies to both server and client side. // // This means less efficient compression as the sliding window from previous messages // will not be used but the memory overhead will be lower if the connections // are long lived and seldom used. // // The message will only be compressed if greater than 512 bytes. CompressionNoContextTakeover CompressionMode = iota // CompressionContextTakeover uses a flate.Reader and flate.Writer per connection. // This enables reusing the sliding window from previous messages. // As most WebSocket protocols are repetitive, this can be very efficient. // It carries an overhead of 8 kB for every connection compared to CompressionNoContextTakeover. // // If the peer negotiates NoContextTakeover on the client or server side, it will be // used instead as this is required by the RFC. CompressionContextTakeover // CompressionDisabled disables the deflate extension. // // Use this if you are using a predominantly binary protocol with very // little duplication in between messages or CPU and memory are more // important than bandwidth. CompressionDisabled )
type Conn ¶
type Conn struct {
// contains filtered or unexported fields
}
Conn provides a wrapper around the browser WebSocket API.
func Accept ¶
func Accept(w http.ResponseWriter, r *http.Request, opts *AcceptOptions) (*Conn, error)
Accept is stubbed out for Wasm.
Example ¶
package main import ( "context" "log" "net/http" "time" "github.com/switchupcb/websocket" "github.com/switchupcb/websocket/wsjson" ) func main() { // This handler accepts a WebSocket connection, reads a single JSON // message from the client and then closes the connection. fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { c, err := websocket.Accept(w, r, nil) if err != nil { log.Println(err) return } defer c.Close(websocket.StatusInternalError, "the sky is falling") ctx, cancel := context.WithTimeout(r.Context(), time.Second*10) defer cancel() var v interface{} err = wsjson.Read(ctx, c, &v) if err != nil { log.Println(err) return } c.Close(websocket.StatusNormalClosure, "") }) err := http.ListenAndServe("localhost:8080", fn) log.Fatal(err) }
Output:
func Dial ¶
Dial creates a new WebSocket connection to the given url with the given options. The passed context bounds the maximum time spent waiting for the connection to open. The returned *http.Response is always nil or a mock. It's only in the signature to match the core API.
Example ¶
package main import ( "context" "log" "time" "github.com/switchupcb/websocket" "github.com/switchupcb/websocket/wsjson" ) func main() { // Dials a server, writes a single JSON message and then // closes the connection. ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() c, _, err := websocket.Dial(ctx, "ws://localhost:8080", nil) if err != nil { log.Fatal(err) } defer c.Close(websocket.StatusInternalError, "the sky is falling") err = wsjson.Write(ctx, c, "hi") if err != nil { log.Fatal(err) } c.Close(websocket.StatusNormalClosure, "") }
Output:
func (*Conn) Close ¶
func (c *Conn) Close(code StatusCode, reason string) error
Close closes the WebSocket with the given code and reason. It will wait until the peer responds with a close frame or the connection is closed. It thus performs the full WebSocket close handshake.
func (*Conn) Read ¶
Read attempts to read a message from the connection. The maximum time spent waiting is bounded by the context.
func (*Conn) Reader ¶
Reader attempts to read a message from the connection. The maximum time spent waiting is bounded by the context.
func (*Conn) SetReadLimit ¶
SetReadLimit implements *Conn.SetReadLimit for wasm.
func (*Conn) Subprotocol ¶
Subprotocol returns the negotiated subprotocol. An empty string means the default protocol.
func (*Conn) Write ¶
Write writes a message of the given type to the connection. Always non blocking.
func (*Conn) Writer ¶
func (c *Conn) Writer(ctx context.Context, typ MessageType) (io.WriteCloser, error)
Writer returns a writer to write a WebSocket data message to the connection. It buffers the entire message in memory and then sends it when the writer is closed.
type DialOptions ¶
type DialOptions struct { // Subprotocols lists the subprotocols to negotiate with the server. Subprotocols []string }
DialOptions represents the options available to pass to Dial.
type MessageType ¶
type MessageType int
MessageType represents the type of a WebSocket message. See https://tools.ietf.org/html/rfc6455#section-5.6
const ( // MessageText is for UTF-8 encoded text messages like JSON. MessageText MessageType = iota + 1 // MessageBinary is for binary messages like protobufs. MessageBinary )
MessageType constants.
func (MessageType) String ¶
func (i MessageType) String() string
type StatusCode ¶
type StatusCode int
StatusCode represents a WebSocket status code. https://tools.ietf.org/html/rfc6455#section-7.4
const ( StatusNormalClosure StatusCode = 1000 StatusGoingAway StatusCode = 1001 StatusProtocolError StatusCode = 1002 StatusUnsupportedData StatusCode = 1003 // StatusNoStatusRcvd cannot be sent in a close message. // It is reserved for when a close message is received without // a status code. StatusNoStatusRcvd StatusCode = 1005 // StatusAbnormalClosure is exported for use only with Wasm. // In non Wasm Go, the returned error will indicate whether the // connection was closed abnormally. StatusAbnormalClosure StatusCode = 1006 StatusInvalidFramePayloadData StatusCode = 1007 StatusPolicyViolation StatusCode = 1008 StatusMessageTooBig StatusCode = 1009 StatusMandatoryExtension StatusCode = 1010 StatusInternalError StatusCode = 1011 StatusServiceRestart StatusCode = 1012 StatusTryAgainLater StatusCode = 1013 StatusBadGateway StatusCode = 1014 // StatusTLSHandshake is only exported for use with Wasm. // In non Wasm Go, the returned error will indicate whether there was // a TLS handshake failure. StatusTLSHandshake StatusCode = 1015 )
https://www.iana.org/assignments/websocket/websocket.xhtml#close-code-number
These are only the status codes defined by the protocol.
You can define custom codes in the 3000-4999 range. The 3000-3999 range is reserved for use by libraries, frameworks and applications. The 4000-4999 range is reserved for private use.
func CloseStatus ¶
func CloseStatus(err error) StatusCode
CloseStatus is a convenience wrapper around Go 1.13's errors.As to grab the status code from a CloseError.
-1 will be returned if the passed error is nil or not a CloseError.
Example ¶
package main import ( "context" "log" "time" "github.com/switchupcb/websocket" ) func main() { // Dials a server and then expects to be disconnected with status code // websocket.StatusNormalClosure. ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() c, _, err := websocket.Dial(ctx, "ws://localhost:8080", nil) if err != nil { log.Fatal(err) } defer c.Close(websocket.StatusInternalError, "the sky is falling") _, _, err = c.Reader(ctx) if websocket.CloseStatus(err) != websocket.StatusNormalClosure { log.Fatalf("expected to be disconnected with StatusNormalClosure but got: %v", err) } }
Output:
func (StatusCode) String ¶
func (i StatusCode) String() string
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package test contains subpackages only used in tests.
|
Package test contains subpackages only used in tests. |
Package wsjs implements typed access to the browser javascript WebSocket API.
|
Package wsjs implements typed access to the browser javascript WebSocket API. |
Package wsjson provides helpers for reading and writing JSON messages.
|
Package wsjson provides helpers for reading and writing JSON messages. |
Package wspb provides helpers for reading and writing protobuf messages.
|
Package wspb provides helpers for reading and writing protobuf messages. |