README
¶
RESP
Low-level primitives for dealing with RESP (REdis Serialization Protocol), client and server-side.
Server Examples
Reading requests:
package main
import (
"fmt"
"strings"
"github.com/bsm/redeo/resp"
)
func main() {
cn := strings.NewReader("*1\r\n$4\r\nPING\r\n*2\r\n$4\r\nEcHO\r\n$5\r\nHeLLO\r\n")
r := resp.NewRequestReader(cn)
// read command
cmd, _ := r.ReadCmd(nil)
fmt.Println(cmd.Name)
for i := 0; i < cmd.ArgN(); i++ {
fmt.Println(i, cmd.Arg(i))
}
// read command, recycle previous instance
cmd, _ = r.ReadCmd(cmd)
fmt.Println(cmd.Name)
for i := 0; i < cmd.ArgN(); i++ {
fmt.Println(i, cmd.Arg(i))
}
}
Writing responses:
package main
import (
"bytes"
"fmt"
"github.com/bsm/redeo/resp"
)
func main() {
buf := new(bytes.Buffer)
w := resp.NewResponseWriter(buf)
// Append OK response
w.AppendOK()
// Append a number
w.AppendInt(33)
// Append an array
w.AppendArrayLen(3)
w.AppendBulkString("Adam")
w.AppendBulkString("Had'em")
w.AppendNil()
// Writer data must be flushed manually
fmt.Println(buf.Len(), w.Buffered())
if err := w.Flush(); err != nil {
panic(err)
}
// Once flushed, it will be sent to the underlying writer
// as a bulk
fmt.Println(buf.Len(), w.Buffered())
fmt.Printf("%q\n", buf.String())
}
Client Examples
Reading requests:
package main
import (
"fmt"
"net"
"github.com/bsm/redeo/resp"
)
func main() {
cn, _ := net.Dial("tcp", "127.0.0.1:6379")
defer cn.Close()
// Wrap connection
w := resp.NewRequestWriter(cn)
r := resp.NewResponseReader(cn)
// Write pipeline
w.WriteCmdString("PING")
w.WriteCmdString("ECHO", "HEllO")
w.WriteCmdString("GET", "key")
w.WriteCmdString("SET", "key", "value")
w.WriteCmdString("DEL", "key")
// Flush pipeline
if err := w.Flush(); err != nil {
panic(err)
}
// Consume responses
for i := 0; i < 5; i++ {
t, err := r.PeekType()
if err != nil {
return
}
switch t {
case resp.TypeInline:
s, _ := r.ReadInlineString()
fmt.Println(s)
case resp.TypeBulk:
s, _ := r.ReadBulkString()
fmt.Println(s)
case resp.TypeInt:
n, _ := r.ReadInt()
fmt.Println(n)
case resp.TypeNil:
_ = r.ReadNil()
fmt.Println(nil)
default:
panic("unexpected response type")
}
}
}
Documentation
¶
Overview ¶
Package resp implements low-level primitives for dealing with RESP (REdis Serialization Protocol). It provides client and server side readers and writers.
Index ¶
- Constants
- func IsProtocolError(err error) bool
- type Command
- type CommandArgument
- type CommandStream
- type CustomResponse
- type NullString
- type RequestReader
- func (r *RequestReader) Buffered() int
- func (r *RequestReader) PeekCmd() (string, error)
- func (r *RequestReader) ReadCmd(cmd *Command) (*Command, error)
- func (r *RequestReader) Reset(rd io.Reader)
- func (r *RequestReader) SkipCmd() error
- func (r *RequestReader) StreamCmd(cmd *CommandStream) (*CommandStream, error)
- type RequestWriter
- func (w *RequestWriter) Buffered() int
- func (w *RequestWriter) CopyBulk(r io.Reader, n int64) error
- func (w *RequestWriter) Flush() error
- func (w *RequestWriter) Reset(wr io.Writer)
- func (w *RequestWriter) WriteBulk(b []byte)
- func (w *RequestWriter) WriteBulkString(s string)
- func (w *RequestWriter) WriteCmd(cmd string, args ...[]byte)
- func (w *RequestWriter) WriteCmdString(cmd string, args ...string)
- func (w *RequestWriter) WriteMultiBulkSize(n int) error
- type ResponseParser
- type ResponseReader
- type ResponseType
- type ResponseWriter
- type Scannable
Examples ¶
Constants ¶
const MaxBufferSize = 64 * 1024
MaxBufferSize is the max request/response buffer size
Variables ¶
This section is empty.
Functions ¶
func IsProtocolError ¶
IsProtocolError returns true if the error is a protocol error
Types ¶
type Command ¶
type Command struct { // Name refers to the command name Name string // Args returns arguments Args []CommandArgument // contains filtered or unexported fields }
Command instances are parsed by a RequestReader
func NewCommand ¶
func NewCommand(name string, args ...CommandArgument) *Command
NewCommand returns a new command instance; useful for tests
func (*Command) SetContext ¶
SetContext sets the request context.
type CommandArgument ¶
type CommandArgument []byte
CommandArgument is an argument of a command
func (CommandArgument) Bytes ¶
func (c CommandArgument) Bytes() []byte
Bytes returns the argument as bytes
func (CommandArgument) Float ¶
func (c CommandArgument) Float() (float64, error)
Float returns the argument as a float64.
func (CommandArgument) Int ¶
func (c CommandArgument) Int() (int64, error)
Int returns the argument as an int64.
func (CommandArgument) String ¶
func (c CommandArgument) String() string
String returns the argument converted to a string
type CommandStream ¶
type CommandStream struct { // Name refers to the command name Name string // contains filtered or unexported fields }
CommandStream instances are created by a RequestReader
func (*CommandStream) ArgN ¶
func (c *CommandStream) ArgN() int
ArgN returns the number of arguments
func (*CommandStream) Context ¶
func (c *CommandStream) Context() context.Context
Context returns the context
func (*CommandStream) Discard ¶
func (c *CommandStream) Discard() error
Discard discards the (remaining) arguments
func (*CommandStream) More ¶
func (c *CommandStream) More() bool
More returns true if there are unread arguments
func (*CommandStream) Next ¶
func (c *CommandStream) Next() (io.Reader, error)
Next returns the next argument as an io.Reader
func (*CommandStream) Reset ¶
func (c *CommandStream) Reset()
Reset discards all data and resets all state
func (*CommandStream) SetContext ¶
func (c *CommandStream) SetContext(ctx context.Context)
SetContext sets the request context.
type CustomResponse ¶
type CustomResponse interface { // AppendTo must be implemented by custom response types AppendTo(w ResponseWriter) }
CustomResponse values implement custom serialization and can be passed to ResponseWriter.Append.
type NullString ¶
NullString is a scannable that can deal with nil values
func (*NullString) ScanResponse ¶
func (s *NullString) ScanResponse(t ResponseType, r ResponseReader) error
ScanResponse implements Scannable
type RequestReader ¶
type RequestReader struct {
// contains filtered or unexported fields
}
RequestReader is used by servers to wrap a client connection and convert requests into commands.
func NewRequestReader ¶
func NewRequestReader(rd io.Reader) *RequestReader
NewRequestReader wraps any reader interface
func (*RequestReader) Buffered ¶
func (r *RequestReader) Buffered() int
Buffered returns the number of unread bytes.
func (*RequestReader) PeekCmd ¶
func (r *RequestReader) PeekCmd() (string, error)
PeekCmd peeks the next command name.
func (*RequestReader) ReadCmd ¶
func (r *RequestReader) ReadCmd(cmd *Command) (*Command, error)
ReadCmd reads the next command. It optionally recycles the cmd passed.
func (*RequestReader) Reset ¶
func (r *RequestReader) Reset(rd io.Reader)
Reset resets the reader to a new reader and recycles internal buffers.
func (*RequestReader) SkipCmd ¶
func (r *RequestReader) SkipCmd() error
SkipCmd skips the next command.
func (*RequestReader) StreamCmd ¶
func (r *RequestReader) StreamCmd(cmd *CommandStream) (*CommandStream, error)
StreamCmd reads the next command as a stream.
type RequestWriter ¶
type RequestWriter struct {
// contains filtered or unexported fields
}
RequestWriter is used by clients to send commands to servers.
func NewRequestWriter ¶
func NewRequestWriter(wr io.Writer) *RequestWriter
NewRequestWriter wraps any Writer interface
func (*RequestWriter) Buffered ¶
func (w *RequestWriter) Buffered() int
Buffered returns the number of buffered bytes
func (*RequestWriter) CopyBulk ¶
func (w *RequestWriter) CopyBulk(r io.Reader, n int64) error
CopyBulk is a low-level method to copy a large bulk of data directly to the writer. For normal operation, use WriteCmd or WriteCmdString.
func (*RequestWriter) Flush ¶
func (w *RequestWriter) Flush() error
Flush flushes the output buffer. Call this after you have completed your pipeline
func (*RequestWriter) Reset ¶
func (w *RequestWriter) Reset(wr io.Writer)
Reset resets the writer with an new interface
func (*RequestWriter) WriteBulk ¶
func (w *RequestWriter) WriteBulk(b []byte)
WriteBulk is a low-level method to write a bulk. For normal operation, use WriteCmd or WriteCmdString.
func (*RequestWriter) WriteBulkString ¶
func (w *RequestWriter) WriteBulkString(s string)
WriteBulkString is a low-level method to write a bulk. For normal operation, use WriteCmd or WriteCmdString.
func (*RequestWriter) WriteCmd ¶
func (w *RequestWriter) WriteCmd(cmd string, args ...[]byte)
WriteCmd writes a full command as part of a pipeline. To execute the pipeline, you must call Flush.
func (*RequestWriter) WriteCmdString ¶
func (w *RequestWriter) WriteCmdString(cmd string, args ...string)
WriteCmdString writes a full command as part of a pipeline. To execute the pipeline, you must call Flush.
func (*RequestWriter) WriteMultiBulkSize ¶
func (w *RequestWriter) WriteMultiBulkSize(n int) error
WriteMultiBulkSize is a low-level method to write a multibulk size. For normal operation, use WriteCmd or WriteCmdString.
type ResponseParser ¶
type ResponseParser interface { // PeekType returns the type of the next response block PeekType() (ResponseType, error) // ReadNil reads a nil value ReadNil() error // ReadBulkString reads a bulk and returns a string ReadBulkString() (string, error) // ReadBulk reads a bulk and returns bytes (optionally appending to a passed p buffer) ReadBulk(p []byte) ([]byte, error) // StreamBulk parses a bulk responses and returns a streaming reader object // Returned responses must be closed. StreamBulk() (io.ReadCloser, error) // ReadInt reads an int value ReadInt() (int64, error) // ReadArrayLen reads the array length ReadArrayLen() (int, error) // ReadError reads an error string ReadError() (string, error) // ReadInlineString reads a status string ReadInlineString() (string, error) // Scan scans results into the given values. Scan(vv ...interface{}) error }
ResponseParser is a basic response parser
type ResponseReader ¶
type ResponseReader interface { ResponseParser // Buffered returns the number of buffered (unread) bytes. Buffered() int // Reset resets the reader to a new reader and recycles internal buffers. Reset(r io.Reader) }
ResponseReader is used by clients to wrap a server connection and parse responses.
func NewResponseReader ¶
func NewResponseReader(rd io.Reader) ResponseReader
NewResponseReader returns ResponseReader, which wraps any reader interface, but normally a net.Conn.
type ResponseType ¶
type ResponseType uint8
ResponseType represents the reply type
const ( TypeUnknown ResponseType = iota TypeArray TypeBulk TypeInline TypeError TypeInt TypeNil )
response type iota
func (ResponseType) String ¶
func (t ResponseType) String() string
String returns the response type description
type ResponseWriter ¶
type ResponseWriter interface { io.Writer // AppendArrayLen appends an array header to the output buffer. AppendArrayLen(n int) // AppendBulk appends bulk bytes to the output buffer. AppendBulk(p []byte) // AppendBulkString appends a bulk string to the output buffer. AppendBulkString(s string) // AppendInline appends inline bytes to the output buffer. AppendInline(p []byte) // AppendInlineString appends an inline string to the output buffer. AppendInlineString(s string) // AppendError appends an error message to the output buffer. AppendError(msg string) // AppendErrorf appends an error message to the output buffer. AppendErrorf(pattern string, args ...interface{}) // AppendInt appends a numeric response to the output buffer. AppendInt(n int64) // AppendNil appends a nil-value to the output buffer. AppendNil() // AppendOK appends "OK" to the output buffer. AppendOK() // Append automatically serialized given values and appends them to the output buffer. // Supported values include: // * nil // * error // * string // * []byte // * bool // * float32, float64 // * int, int8, int16, int32, int64 // * uint, uint8, uint16, uint32, uint64 // * CustomResponse instances // * slices and maps of any of the above Append(v interface{}) error // CopyBulk copies n bytes from a reader. // This call may flush pending buffer to prevent overflows. CopyBulk(src io.Reader, n int64) error // Buffered returns the number of pending bytes. Buffered() int // Flush flushes pending buffer. Flush() error // Reset resets the writer to a new writer and recycles internal buffers. Reset(w io.Writer) }
ResponseWriter is used by servers to wrap a client connection and send protocol-compatible responses in buffered pipelines.
func NewResponseWriter ¶
func NewResponseWriter(wr io.Writer) ResponseWriter
NewResponseWriter wraps any writer interface, but normally a net.Conn.
type Scannable ¶
type Scannable interface { // ScanResponse scans theresponse from the reader ScanResponse(t ResponseType, r ResponseReader) error }
Scannable interfaces may implement custom Scan behaviour