Documentation ¶
Overview ¶
Example (CrossOrigin) ¶
package main import ( "log" "net/http" "gfx.cafe/open/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/internal/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/internal/examples/chat }
Output:
Example (WriteOnly) ¶
package main import ( "context" "log" "net/http" "time" "gfx.cafe/open/websocket" "gfx.cafe/open/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.CloseNow() 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) CloseNow() 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 and there is an active read or write goroutine, 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 the real addresses for connections obtained from websocket.Accept. But for connections obtained from websocket.Dial, a mock net.Addr will be returned that gives "websocket" for Network() and "websocket/unknown-addr" for String(). This is because websocket.Dial only exposes a io.ReadWriteCloser instead of the full net.Conn to us.
When running as WASM, the Addr methods will always return the mock address described above.
A received StatusNormalClosure or StatusGoingAway close frame will be translated to io.EOF when reading.
Furthermore, the ReadLimit is set to -1 to disable it.
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 Works in all browsers except Safari which does not implement the deflate extension.
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" "gfx.cafe/open/websocket" "gfx.cafe/open/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.CloseNow() 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" "gfx.cafe/open/websocket" "gfx.cafe/open/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.CloseNow() 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) CloseNow ¶ added in v1.10.0
CloseNow closes the WebSocket connection without attempting a close handshake. Use when you do not want the overhead of the close handshake.
note: No different from Close(StatusGoingAway, "") in WASM as there is no way to close a WebSocket without the close handshake.
func (*Conn) Ping ¶
Ping is mocked out for Wasm.
Example ¶
package main import ( "context" "log" "time" "gfx.cafe/open/websocket" ) func main() { // Dials a server and pings it 5 times. 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.CloseNow() // Required to read the Pongs from the server. ctx = c.CloseRead(ctx) for i := 0; i < 5; i++ { err = c.Ping(ctx) if err != nil { log.Fatal(err) } } c.Close(websocket.StatusNormalClosure, "") }
Output:
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" "gfx.cafe/open/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.CloseNow() _, _, 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
Directories ¶
Path | Synopsis |
---|---|
internal
|
|
test
Package test contains subpackages only used in tests.
|
Package test contains subpackages only used in tests. |
wsjs
Package wsjs implements typed access to the browser javascript WebSocket API.
|
Package wsjs implements typed access to the browser javascript WebSocket API. |
thirdparty
Module
|
|
Package wsjson provides helpers for reading and writing JSON messages.
|
Package wsjson provides helpers for reading and writing JSON messages. |