add the new neffos StackExchange feature to the type aliases and shortcuts of the websocket subpackage and auto-enable debug mode on websocket MVC application when iris logger's level is set to debug

Former-commit-id: 4d8cb79d01a4172fc1ed7a9b626da0228d902b3c
This commit is contained in:
Gerasimos (Makis) Maropoulos 2019-07-11 12:59:11 +03:00
parent 82d645e3cb
commit 33dfb42d73
10 changed files with 83 additions and 57 deletions

View File

@ -7,18 +7,12 @@ import (
"github.com/kataras/iris"
"github.com/kataras/iris/mvc"
"github.com/kataras/iris/websocket"
"github.com/kataras/neffos"
)
func main() {
app := iris.New()
app.Logger().SetLevel("debug")
// optionally enable debug messages to the neffos real-time framework
// and print them through the iris' logger.
neffos.EnableDebug(app.Logger())
// load templates.
app.RegisterView(iris.HTML("./views", ".html"))
@ -33,7 +27,7 @@ func main() {
)
m.HandleWebsocket(&websocketController{Namespace: "default", Age: 42, Otherstring: "other string"})
websocketServer := neffos.New(websocket.DefaultGorillaUpgrader, m)
websocketServer := websocket.New(websocket.DefaultGorillaUpgrader, m)
websocketAPI.Get("/", websocket.Handler(websocketServer))
// http://localhost:8080
@ -51,10 +45,10 @@ func decrement() uint64 {
}
type websocketController struct {
*neffos.NSConn `stateless:"true"`
Namespace string
Age int
Otherstring string
*websocket.NSConn `stateless:"true"`
Namespace string
Age int
Otherstring string
Logger LoggerService
}
@ -64,13 +58,13 @@ type websocketController struct {
// return "default"
// }
func (c *websocketController) OnNamespaceDisconnect(msg neffos.Message) error {
func (c *websocketController) OnNamespaceDisconnect(msg websocket.Message) error {
c.Logger.Log("Disconnected")
// visits--
newCount := decrement()
// This will call the "OnVisit" event on all clients, except the current one,
// (it can't because it's left but for any case use this type of design)
c.Conn.Server().Broadcast(nil, neffos.Message{
c.Conn.Server().Broadcast(nil, websocket.Message{
Namespace: msg.Namespace,
Event: "OnVisit",
Body: []byte(fmt.Sprintf("%d", newCount)),
@ -79,7 +73,7 @@ func (c *websocketController) OnNamespaceDisconnect(msg neffos.Message) error {
return nil
}
func (c *websocketController) OnNamespaceConnected(msg neffos.Message) error {
func (c *websocketController) OnNamespaceConnected(msg websocket.Message) error {
// println("Broadcast prefix is: " + c.BroadcastPrefix)
c.Logger.Log("Connected")
@ -91,7 +85,7 @@ func (c *websocketController) OnNamespaceConnected(msg neffos.Message) error {
//
// There are many ways that u can do it and faster, for example u can just send a new visitor
// and client can increment itself, but here we are just "showcasing" the websocket controller.
c.Conn.Server().Broadcast(nil, neffos.Message{
c.Conn.Server().Broadcast(nil, websocket.Message{
Namespace: msg.Namespace,
Event: "OnVisit",
Body: []byte(fmt.Sprintf("%d", newCount)),
@ -100,7 +94,7 @@ func (c *websocketController) OnNamespaceConnected(msg neffos.Message) error {
return nil
}
func (c *websocketController) OnChat(msg neffos.Message) error {
func (c *websocketController) OnChat(msg websocket.Message) error {
ctx := websocket.GetContext(c.Conn)
ctx.Application().Logger().Infof("[IP: %s] [ID: %s] broadcast to other clients the message [%s]",

View File

@ -0,0 +1,14 @@
# Websocket
[WebSocket](https://wikipedia.org/wiki/WebSocket) is a protocol that enables two-way persistent communication channels over TCP connections. It is used for applications such as chat, stock tickers, games, anywhere you want real-time functionality in a web application.
Iris websocket library is now merged with the [neffos real-time framework](https://github.com/kataras/neffos) and Iris-specific helpers and type aliases live on the [iris/websocket](https://github.com/kataras/iris/tree/master/websocket) subpackage. Learn neffos from its [wiki](https://github.com/kataras/neffos#learning-neffos).
Helpers and type aliases improves your code speed when writing a websocket module.
For example, instead of importing both `kataras/iris/websocket` - in order to use its `websocket.Handler` - and `github.com/kataras/neffos` - to create a new websocket server `neffos.New` - you can use the `websocket.New` instead, another example is the `neffos.Conn` which can be declared as `websocket.Conn`.
All neffos and its subpackage's types and package-level functions exist as type aliases on the `kataras/iris/websocket` package too, there are too many of those and there is no need to write each one of those here, some common types:
- `github.com/kataras/neffos/#Conn` -> `github.com/kataras/iris/websocket/#Conn`
- `github.com/kataras/neffos/gorilla/#DefaultUpgrader` -> `github.com/kataras/iris/websocket/#DefaultGorillaUpgrader`
- `github.com/kataras/neffos/stackexchange/redis/#NewStackExchange` -> `github.com/kataras/iris/websocket/#NewRedisStackExchange`

View File

@ -10,8 +10,6 @@ import (
"time"
"github.com/kataras/iris/websocket"
"github.com/kataras/neffos"
)
const (
@ -23,17 +21,17 @@ const (
// this can be shared with the server.go's.
// `NSConn.Conn` has the `IsClient() bool` method which can be used to
// check if that's is a client or a server-side callback.
var clientEvents = neffos.Namespaces{
namespace: neffos.Events{
neffos.OnNamespaceConnected: func(c *neffos.NSConn, msg neffos.Message) error {
var clientEvents = websocket.Namespaces{
namespace: websocket.Events{
websocket.OnNamespaceConnected: func(c *websocket.NSConn, msg websocket.Message) error {
log.Printf("connected to namespace: %s", msg.Namespace)
return nil
},
neffos.OnNamespaceDisconnect: func(c *neffos.NSConn, msg neffos.Message) error {
websocket.OnNamespaceDisconnect: func(c *websocket.NSConn, msg websocket.Message) error {
log.Printf("disconnected from namespace: %s", msg.Namespace)
return nil
},
"chat": func(c *neffos.NSConn, msg neffos.Message) error {
"chat": func(c *websocket.NSConn, msg websocket.Message) error {
log.Printf("%s", string(msg.Body))
return nil
},
@ -44,7 +42,7 @@ func main() {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(dialAndConnectTimeout))
defer cancel()
client, err := neffos.Dial(ctx, websocket.DefaultGorillaDialer, endpoint, clientEvents)
client, err := websocket.Dial(ctx, websocket.DefaultGorillaDialer, endpoint, clientEvents)
if err != nil {
panic(err)
}

View File

@ -6,8 +6,6 @@ import (
"github.com/kataras/iris"
"github.com/kataras/iris/websocket"
"github.com/kataras/neffos"
// Used when "enableJWT" constant is true:
"github.com/dgrijalva/jwt-go"
jwtmiddleware "github.com/iris-contrib/middleware/jwt"
@ -17,10 +15,10 @@ import (
const enableJWT = true
const namespace = "default"
// if namespace is empty then simply neffos.Events{...} can be used instead.
var serverEvents = neffos.Namespaces{
namespace: neffos.Events{
neffos.OnNamespaceConnected: func(nsConn *neffos.NSConn, msg neffos.Message) error {
// if namespace is empty then simply websocket.Events{...} can be used instead.
var serverEvents = websocket.Namespaces{
namespace: websocket.Events{
websocket.OnNamespaceConnected: func(nsConn *websocket.NSConn, msg websocket.Message) error {
// with `websocket.GetContext` you can retrieve the Iris' `Context`.
ctx := websocket.GetContext(nsConn.Conn)
@ -29,11 +27,11 @@ var serverEvents = neffos.Namespaces{
ctx.RemoteAddr())
return nil
},
neffos.OnNamespaceDisconnect: func(nsConn *neffos.NSConn, msg neffos.Message) error {
websocket.OnNamespaceDisconnect: func(nsConn *websocket.NSConn, msg websocket.Message) error {
log.Printf("[%s] disconnected from namespace [%s]", nsConn, msg.Namespace)
return nil
},
"chat": func(nsConn *neffos.NSConn, msg neffos.Message) error {
"chat": func(nsConn *websocket.NSConn, msg websocket.Message) error {
// room.String() returns -> NSConn.String() returns -> Conn.String() returns -> Conn.ID()
log.Printf("[%s] sent: %s", nsConn, string(msg.Body))
@ -48,7 +46,7 @@ var serverEvents = neffos.Namespaces{
func main() {
app := iris.New()
websocketServer := neffos.New(
websocketServer := websocket.New(
websocket.DefaultGorillaUpgrader, /* DefaultGobwasUpgrader can be used too. */
serverEvents)
@ -76,7 +74,7 @@ func main() {
//
// Check for token through the jwt middleware
// on websocket connection or on any event:
/* websocketServer.OnConnect = func(c *neffos.Conn) error {
/* websocketServer.OnConnect = func(c *websocket.Conn) error {
ctx := websocket.GetContext(c)
if err := j.CheckJWT(ctx); err != nil {
// will send the above error on the client

View File

@ -5,8 +5,6 @@ import (
"github.com/kataras/iris"
"github.com/kataras/iris/websocket"
"github.com/kataras/neffos"
)
type clientPage struct {
@ -26,8 +24,8 @@ func main() {
// and contains only one registered event which is the `OnNativeMessage`.
// When `Events{...}` is used instead of `Namespaces{ "namespaceName": Events{...}}`
// then the namespace is empty "".
ws := neffos.New(websocket.DefaultGorillaUpgrader, neffos.Events{
neffos.OnNativeMessage: func(nsConn *neffos.NSConn, msg neffos.Message) error {
ws := websocket.New(websocket.DefaultGorillaUpgrader, websocket.Events{
websocket.OnNativeMessage: func(nsConn *websocket.NSConn, msg websocket.Message) error {
log.Printf("Server got: %s from [%s]", msg.Body, nsConn.Conn.ID())
nsConn.Conn.Server().Broadcast(nsConn, msg)
@ -35,12 +33,12 @@ func main() {
},
})
ws.OnConnect = func(c *neffos.Conn) error {
ws.OnConnect = func(c *websocket.Conn) error {
log.Printf("[%s] Connected to server!", c.ID())
return nil
}
ws.OnDisconnect = func(c *neffos.Conn) {
ws.OnDisconnect = func(c *websocket.Conn) {
log.Printf("[%s] Disconnected from server", c.ID())
}

2
go.mod
View File

@ -15,7 +15,7 @@ require (
github.com/iris-contrib/go.uuid v2.0.0+incompatible
github.com/json-iterator/go v1.1.6 // vendor removed.
github.com/kataras/golog v0.0.0-20180321173939-03be10146386
github.com/kataras/neffos v0.0.5
github.com/kataras/neffos v0.0.6
github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d // indirect
github.com/microcosm-cc/bluemonday v1.0.2
github.com/ryanuber/columnize v2.1.0+incompatible

View File

@ -64,6 +64,7 @@ func New(party router.Party) *Application {
if HeroDependencies {
values = hero.Dependencies().Clone()
}
return newApp(party, values)
}
@ -195,6 +196,10 @@ var _ websocket.ConnHandler = (*Application)(nil)
// It returns a collection of namespace and events that
// were registered through `HandleWebsocket` controllers.
func (app *Application) GetNamespaces() websocket.Namespaces {
if golog.Default.Level == golog.DebugLevel {
websocket.EnableDebug(golog.Default)
}
makeInjector := func(injector *di.StructInjector) websocket.StructInjector {
return func(_ reflect.Type, nsConn *websocket.NSConn) reflect.Value {
v := injector.Acquire()
@ -212,7 +217,6 @@ func (app *Application) GetNamespaces() websocket.Namespaces {
wsInjector := makeInjector(c.injector)
s := websocket.NewStruct(c.Value).SetInjector(wsInjector)
websocketControllers = append(websocketControllers, s)
}
}

View File

@ -335,22 +335,20 @@ func (r *Service) GetKeys(prefix string) ([]string, error) {
return r.getKeys(prefix)
}
// GetBytes returns value, err by its key
// you can use utils.Deserialize((.GetBytes("yourkey"),&theobject{})
//returns nil and a filled error if something wrong happens
func (r *Service) GetBytes(key string) ([]byte, error) {
var redisVal []byte
mn := radix.MaybeNil{Rcv: &redisVal}
err := r.pool.Do(radix.Cmd(&mn, "GET", r.Config.Prefix+key))
if err != nil {
return nil, err
}
if mn.Nil {
return nil, ErrKeyNotFound.Format(key)
}
// // GetBytes returns bytes representation of a value based on given "key".
// func (r *Service) GetBytes(key string) ([]byte, error) {
// var redisVal []byte
// mn := radix.MaybeNil{Rcv: &redisVal}
// err := r.pool.Do(radix.Cmd(&mn, "GET", r.Config.Prefix+key))
// if err != nil {
// return nil, err
// }
// if mn.Nil {
// return nil, ErrKeyNotFound.Format(key)
// }
return redisVal, nil
}
// return redisVal, nil
// }
// Delete removes redis entry by specific key
func (r *Service) Delete(key string) error {

View File

@ -4,11 +4,17 @@ import (
"github.com/kataras/iris/context"
"github.com/kataras/neffos"
"github.com/kataras/neffos/gobwas"
"github.com/kataras/neffos/gorilla"
"github.com/kataras/neffos/stackexchange/redis"
)
var (
// EnableDebug enables debug mode for websocket module,
// for MVC this is done automatically
// when the app's logger level is set to "debug".
EnableDebug = neffos.EnableDebug
// GorillaUpgrader is an upgrader type for the gorilla/websocket subprotocol implementation.
// Should be used on `New` to construct the websocket server.
GorillaUpgrader = gorilla.Upgrader
@ -32,6 +38,9 @@ var (
DefaultIDGenerator = func(ctx context.Context) string {
return neffos.DefaultIDGenerator(ctx.ResponseWriter(), ctx.Request())
}
// NewRedisStackExchange returns a new redis StackExchange.
// The "channel" input argument is the channel prefix for publish and subscribe.
NewRedisStackExchange = redis.NewStackExchange
// GorillaDialer is a `Dialer` type for the gorilla/websocket subprotocol implementation.
// Should be used on `Dial` to create a new client/client-side connection.

View File

@ -6,6 +6,7 @@ import (
"github.com/kataras/neffos"
"github.com/kataras/neffos/gobwas"
"github.com/kataras/neffos/gorilla"
"github.com/kataras/neffos/stackexchange/redis"
)
type (
@ -76,4 +77,16 @@ type (
// when incoming native message then the `Message.Event` is the `OnNativeMessage`,
// native messages are allowed only when an empty namespace("") and its `OnNativeMessage` callback are present.
Message = neffos.Message
// StackExchange is an optional interface
// that can be used to change the way neffos
// sends messages to its clients, i.e
// communication between multiple neffos servers.
//
// See `NewRedisStackExchange` to create a new redis StackExchange.
StackExchange = neffos.StackExchange
// RedisStackExchange is a `neffos.StackExchange` for redis.
RedisStackExchange = redis.StackExchange
// RedisConfig is used on the `NewRedisStackExchange` package-level function.
// Can be used to customize the redis client dialer.
RedisConfig = redis.Config
)