mirror of https://github.com/tidwall/redcon.git
implement custom connection handler
This commit is contained in:
parent
bc9875b4b0
commit
05069c3c85
51
redcon.go
51
redcon.go
|
@ -105,6 +105,8 @@ type Conn interface {
|
||||||
// }
|
// }
|
||||||
// }()
|
// }()
|
||||||
Detach() DetachedConn
|
Detach() DetachedConn
|
||||||
|
// Hijack returns a connection that's only partially managed by redcon
|
||||||
|
Hijack(handler func(conn HijackedConn) error) error
|
||||||
// ReadPipeline returns all commands in current pipeline, if any
|
// ReadPipeline returns all commands in current pipeline, if any
|
||||||
// The commands are removed from the pipeline.
|
// The commands are removed from the pipeline.
|
||||||
ReadPipeline() []Command
|
ReadPipeline() []Command
|
||||||
|
@ -401,6 +403,17 @@ func handle(s *Server, c *conn) {
|
||||||
}()
|
}()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if c.connHandler != nil {
|
||||||
|
err = c.connHandler(c)
|
||||||
|
if err, ok := err.(*errProtocol); ok {
|
||||||
|
// All protocol errors should attempt a response to
|
||||||
|
// the client. Ignore write errors.
|
||||||
|
c.wr.WriteError("ERR " + err.Error())
|
||||||
|
c.wr.Flush()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err = func() error {
|
err = func() error {
|
||||||
// read commands and feed back to the client
|
// read commands and feed back to the client
|
||||||
for {
|
for {
|
||||||
|
@ -453,6 +466,7 @@ type conn struct {
|
||||||
closed bool
|
closed bool
|
||||||
cmds []Command
|
cmds []Command
|
||||||
idleClose time.Duration
|
idleClose time.Duration
|
||||||
|
connHandler func(c HijackedConn) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) Close() error {
|
func (c *conn) Close() error {
|
||||||
|
@ -486,6 +500,15 @@ func (c *conn) PeekPipeline() []Command {
|
||||||
func (c *conn) NetConn() net.Conn {
|
func (c *conn) NetConn() net.Conn {
|
||||||
return c.conn
|
return c.conn
|
||||||
}
|
}
|
||||||
|
func (c *conn) ReadCommand() (Command, error) {
|
||||||
|
return c.rd.ReadCommand()
|
||||||
|
}
|
||||||
|
func (c *conn) ReadCommands() ([]Command, error) {
|
||||||
|
return c.rd.readCommands(nil)
|
||||||
|
}
|
||||||
|
func (c *conn) Flush() error {
|
||||||
|
return c.wr.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
// BaseWriter returns the underlying connection writer, if any
|
// BaseWriter returns the underlying connection writer, if any
|
||||||
func BaseWriter(c Conn) *Writer {
|
func BaseWriter(c Conn) *Writer {
|
||||||
|
@ -505,6 +528,18 @@ type DetachedConn interface {
|
||||||
Flush() error
|
Flush() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HijackedConn represents a connection that is hijacked from the server to allow for custom command read functionality
|
||||||
|
type HijackedConn interface {
|
||||||
|
// DetachedConn is the original connection
|
||||||
|
DetachedConn
|
||||||
|
// ReadCommand reads the next client command.
|
||||||
|
ReadCommand() (Command, error)
|
||||||
|
// ReadCommands reads the next pipeline commands.
|
||||||
|
ReadCommands() ([]Command, error)
|
||||||
|
// Flush flushes any writes to the network.
|
||||||
|
Flush() error
|
||||||
|
}
|
||||||
|
|
||||||
// Detach removes the current connection from the server loop and returns
|
// Detach removes the current connection from the server loop and returns
|
||||||
// a detached connection. This is useful for operations such as PubSub.
|
// a detached connection. This is useful for operations such as PubSub.
|
||||||
// The detached connection must be closed by calling Close() when done.
|
// The detached connection must be closed by calling Close() when done.
|
||||||
|
@ -545,6 +580,21 @@ func (dc *detachedConn) ReadCommand() (Command, error) {
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *conn) Hijack(handler func(c HijackedConn) error) error {
|
||||||
|
c.cmds = nil
|
||||||
|
c.connHandler = handler
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type hijackedConn struct {
|
||||||
|
*conn
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadCommands reads the next pipeline commands
|
||||||
|
func (c *hijackedConn) ReadCommands() ([]Command, error) {
|
||||||
|
return c.rd.readCommands(nil)
|
||||||
|
}
|
||||||
|
|
||||||
// Command represent a command
|
// Command represent a command
|
||||||
type Command struct {
|
type Command struct {
|
||||||
// Raw is a encoded RESP message.
|
// Raw is a encoded RESP message.
|
||||||
|
@ -709,6 +759,7 @@ func (w *Writer) WriteRaw(data []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteAny writes any type to client.
|
// WriteAny writes any type to client.
|
||||||
|
//
|
||||||
// nil -> null
|
// nil -> null
|
||||||
// error -> error (adds "ERR " when first word is not uppercase)
|
// error -> error (adds "ERR " when first word is not uppercase)
|
||||||
// string -> bulk-string
|
// string -> bulk-string
|
||||||
|
|
Loading…
Reference in New Issue