Documentation ¶
Overview ¶
Package wsutil provides utilities for working with WebSocket protocol.
Overview:
// Read masked text message from peer and check utf8 encoding. header, err := ws.ReadHeader(conn) if err != nil { // handle err } // Prepare to read payload. r := io.LimitReader(conn, header.Length) r = wsutil.NewCipherReader(r, header.Mask) r = wsutil.NewUTF8Reader(r) payload, err := ioutil.ReadAll(r) if err != nil { // handle err }
You could get the same behavior using just `wsutil.Reader`:
r := wsutil.Reader{ Source: conn, CheckUTF8: true, } payload, err := ioutil.ReadAll(r) if err != nil { // handle err }
Or even simplest:
payload, err := wsutil.ReadClientText(conn) if err != nil { // handle err }
Package is also exports tools for buffered writing:
// Create buffered writer, that will buffer output bytes and send them as // 128-length fragments (with exception on large writes, see the doc). writer := wsutil.NewWriterSize(conn, ws.StateServerSide, ws.OpText, 128) _, err := io.CopyN(writer, rand.Reader, 100) if err == nil { err = writer.Flush() } if err != nil { // handle error }
For more utils and helpers see the documentation.
Index ¶
- Variables
- func PutWriter(w *Writer)
- func WriteMessage(w io.Writer, s ws.State, op ws.OpCode, p []byte) error
- type CipherReader
- type CipherWriter
- type ControlWriter
- type FrameHandlerFunc
- type Message
- type Reader
- type Writer
- func GetWriter(dest io.Writer, state ws.State, op ws.OpCode, n int) *Writer
- func NewWriter(dest io.Writer, state ws.State, op ws.OpCode) *Writer
- func NewWriterBuffer(dest io.Writer, state ws.State, op ws.OpCode, buf []byte) *Writer
- func NewWriterBufferSize(dest io.Writer, state ws.State, op ws.OpCode, n int) *Writer
- func NewWriterSize(dest io.Writer, state ws.State, op ws.OpCode, n int) *Writer
- func (w *Writer) Available() int
- func (w *Writer) Buffered() int
- func (w *Writer) Flush() error
- func (w *Writer) FlushFragment() error
- func (w *Writer) ReadFrom(src io.Reader) (n int64, err error)
- func (w *Writer) Reset(dest io.Writer, state ws.State, op ws.OpCode)
- func (w *Writer) Size() int
- func (w *Writer) Write(p []byte) (n int, err error)
- func (w *Writer) WriteThrough(p []byte) (n int, err error)
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotEmpty is returned by Writer.WriteThrough() to indicate that buffer is // not empty and write through could not be done. That is, caller should call // Writer.FlushFragment() to make buffer empty. ErrNotEmpty = fmt.Errorf("writer not empty") // ErrControlOverflow is returned by ControlWriter.Write() to indicate that // no more data could be written to the underlying io.Writer because // MaxControlFramePayloadSize limit is reached. ErrControlOverflow = fmt.Errorf("control frame payload overflow") )
var DefaultWriteBuffer = 4096
DefaultWriteBuffer contains size of Writer's default buffer. It used by Writer constructor functions.
var ErrNoFrameAdvance = errors.New("no frame advance")
ErrNoFrameAdvance means that Reader's Read() method was called without preceding NextFrame() call.
Functions ¶
func WriteMessage ¶
WriteMessage is a helper function that writes message to the w. It constructs single frame with given operation code and payload. It uses given state to prepare side-dependent things, like cipher payload bytes from client to server. It will not mutate p bytes if cipher must be made.
If you want to write message in fragmented frames, use Writer instead.
Types ¶
type CipherReader ¶
type CipherReader struct {
// contains filtered or unexported fields
}
CipherReader implements io.Reader that applies xor-cipher to the bytes read from source. It could help to unmask WebSocket frame payload on the fly.
func NewCipherReader ¶
func NewCipherReader(r io.Reader, mask [4]byte) *CipherReader
NewCipherReader creates xor-cipher reader from r with given mask.
type CipherWriter ¶
type CipherWriter struct {
// contains filtered or unexported fields
}
CipherWriter implements io.Writer that applies xor-cipher to the bytes written to the destination writer. It does not modify the original bytes.
func NewCipherWriter ¶
func NewCipherWriter(w io.Writer, mask [4]byte) *CipherWriter
NewCipherWriter creates xor-cipher writer to w with given mask.
type ControlWriter ¶
type ControlWriter struct {
// contains filtered or unexported fields
}
ControlWriter is a wrapper around Writer that contains some guards for buffered writes of control frames.
func NewControlWriter ¶
NewControlWriter contains ControlWriter with Writer inside whose buffer size is at most ws.MaxControlFramePayloadSize + ws.MaxHeaderSize.
func NewControlWriterBuffer ¶
func NewControlWriterBuffer(dest io.Writer, state ws.State, op ws.OpCode, buf []byte) *ControlWriter
NewControlWriterBuffer returns a new ControlWriter with buf as a buffer.
Note that it reserves x bytes of buf for header data, where x could be ws.MinHeaderSize or ws.MinHeaderSize+4 (depending on state). At most (ws.MaxControlFramePayloadSize + x) bytes of buf will be used.
It panics if len(buf) <= ws.MinHeaderSize + x.
func (*ControlWriter) Flush ¶
func (c *ControlWriter) Flush() error
Flush flushes all buffered data to the underlying io.Writer.
type FrameHandlerFunc ¶
FrameHandlerFunc handles parsed frame header and its body represented by io.Reader.
Note that reader represents already unmasked body.
type Message ¶
Message represents a message from peer, that could be presented in one or more frames. That is, it contains payload of all message fragments and operation code of initial frame for this message.
func ReadMessage ¶
ReadMessage is a helper function that reads next message from r. It appends received message(s) to the third argument and returns the result of it and an error if some failure happened. That is, it probably could receive more than one message when peer sending fragmented message in multiple frames and want to send some control frame between fragments. Then returned slice will contain those control frames at first, and then result of gluing fragments.
TODO(gobwas): add DefaultReader with buffer size options.
type Reader ¶
type Reader struct { Source io.Reader State ws.State // SkipHeaderCheck disables checking header bits to be RFC6455 compliant. SkipHeaderCheck bool OnContinuation FrameHandlerFunc OnIntermediate FrameHandlerFunc // contains filtered or unexported fields }
Reader is a wrapper around source io.Reader which represents WebSocket connection. It contains options for reading messages from source.
Reader implements io.Reader, which Read() method reads payload of incoming WebSocket frames. It also takes care on fragmented frames and possibly intermediate control frames between them.
Note that Reader's methods are not goroutine safe.
func NewReader ¶
NewReader creates new frame reader that reads from r keeping given state to make some protocol validity checks when it needed.
func (*Reader) Discard ¶
Discard discards current message unread bytes. It discards all frames of fragmented message.
func (*Reader) NextFrame ¶
NextFrame prepares r to read next message. It returns received frame header and non-nil error on failure.
Note that next NextFrame() call must be done after receiving or discarding all current message bytes.
func (*Reader) Read ¶
Read implements io.Reader. It reads the next message payload into p. It takes care on fragmented messages.
The error is io.EOF only if all of message bytes were read. If an io.EOF happens during reading some but not all the message bytes Read() returns io.ErrUnexpectedEOF.
The error is ErrNoFrameAdvance if no NextFrame() call was made before reading next message bytes.
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer contains logic of buffering output data into a WebSocket fragments. It is much the same as bufio.Writer, except the thing that it works with WebSocket frames, not the raw data.
Writer writes frames with specified OpCode. It uses ws.State to decide whether the output frames must be masked.
Note that it does not check control frame size or other RFC rules. That is, it must be used with special care to write control frames without violation of RFC. You could use ControlWriter that wraps Writer and contains some guards for writing control frames.
If an error occurs writing to a Writer, no more data will be accepted and all subsequent writes will return the error. After all data has been written, the client should call the Flush() method to guarantee all data has been forwarded to the underlying io.Writer.
func GetWriter ¶
GetWriter tries to reuse Writer getting it from the pool.
This function is intended for memory consumption optimizations, because NewWriter*() functions make allocations for inner buffer.
Note the it ceils n to the power of two.
If you have your own bytes buffer pool you could use NewWriterBuffer to use pooled bytes in writer.
func NewWriterBuffer ¶
NewWriterBuffer returns a new Writer with buf as a buffer.
Note that it reserves x bytes of buf for header data, where x is in range [ws.MinHeaderSize,ws.MaxHeaderSize] (depending on state and buf size).
You could use ws.HeaderSize() to calculate number of bytes needed to store header data.
It panics if len(buf) is too small to fit header and payload data.
func NewWriterBufferSize ¶
NewWriterBufferSize returns a new Writer whose buffer size is equal to n. If n <= ws.MinHeaderSize then the default buffer size is used.
Note that Writer will reserve x bytes for header data, where x is in range [ws.MinHeaderSize,ws.MaxHeaderSize]. That is, frames flushed by Writer will not have payload length equal to n, except the case when Write() is called on empty Writer with len(p) > n.
func NewWriterSize ¶
NewWriterSize returns a new Writer whose buffer size is at most n + ws.MaxHeaderSize. That is, output frames payload length could be up to n, except the case when Write() is called on empty Writer with len(p) > n.
If n <= 0 then the default buffer size is used as Writer's buffer size.
func (*Writer) Buffered ¶
Buffered returns the number of bytes that have been written into the current buffer.
func (*Writer) Flush ¶
Flush writes any buffered data to the underlying io.Writer. It sends the frame with "fin" flag set to true.
If no Write() or ReadFrom() was made, then Flush() does nothing.
func (*Writer) FlushFragment ¶
FlushFragment writes any buffered data to the underlying io.Writer. It sends the frame with "fin" flag set to false.
func (*Writer) Reset ¶
Reset discards any buffered data, clears error, and resets w to have given state and write frames with given OpCode to dest.