neffos
neffos copied to clipboard
[INFO] How to integrate with Echo framework
Hi @kataras, I started to use neffos nearly weak ago and i really like it, where i work we decide to move into real time aplication, and i searched for a good socket package, i already used iris and i really like how it works, i was working with websockets of iris and when i updated iris i see some errors (i was in trubles before because updates of other libraries we use), then i read the documentation and i've changed all.
I also integrate the sockets with echo framework and i wold like to leave here how i made it for anyone who need it and also i think it will be good for this greate library if they have examples of implementatios with other to.
Then here is the code:
package main
import (
"github.com/labstack/echo"
"github.com/kataras/neffos"
"github.com/kataras/neffos/gorilla"
"github.com/labstack/echo"
)
type serverConn struct {
*neffos.NSConn
}
func main() {
router := echo.New()
controller := new(serverConn)
events := neffos.NewStruct(controller).
SetNamespace("default").
SetEventMatcher(neffos.EventTrimPrefixMatcher("On"))
websocketServer := neffos.New(
gorilla.DefaultUpgrader, /* DefaultGobwasUpgrader can be used too. */
events)
// Wrap the web socket handler with echo function to be compatible, both use http library to work
router.Any("/echo", echo.WrapHandler(websocketServer), deleteOrigin)
if err := router.Start(":8080"); err != nil {
log.Fatalf("error in ListenAndServe: %s", err)
}
}
// deleteOrigin allows others origins than local access to sockets
// if we avoid this handler then we can't connect from servers in other ports or routes
// NOTE: This isn't the best way to do it, but i can't found another way to do it.
func deleteOrigin(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
c.Request().Header.Del("Origin")
return next(c)
}
}
func (c *serverConn) OnNamespaceConnected(msg neffos.Message) error {
log.Printf("[%s] connected to namespace [%s]",
c.Conn, msg.Namespace)
return nil
}
func (c *serverConn) OnNamespaceDisconnect(msg neffos.Message) error {
log.Printf("[%s] disconnected from namespace [%s]", c.Conn, msg.Namespace)
return nil
}
func (c *serverConn) OnChat(msg neffos.Message) error {
log.Printf("[%s] sent: %s", c.Conn, string(msg.Body))
c.Conn.Server().Broadcast(c.Conn, msg)
return nil
}
This is only for the server file, if anyone want to test it use with the files in the route: _examples/basic/browser
One las thing: I don't know how to acces to the context of the request.
Looks great @xXLokerXx, thanks, this library is designed for every Gopher.
About your question on
One las thing: I don't know how to acces to the context of the request.
There are many ways but the easiest is to wrap the neffos.Socket with a custom socket structure and create a custom echo Handler
which will put the the original Echo Context to that socket wrapper.
You can see how Iris does that at: https://github.com/kataras/iris/blob/4e1c4ac355ad0f0b176ff223ae70e3f32a71bd4a/websocket/websocket.go#L151-L192
An alternative way would be to use the Request().WithContext
and provide a key and a value which will be the echo Context but I really don't recommend that one.
I just did a change:
from this: router.GET("/echo", echo.WrapHandler(websocketServer), deleteOrigin)
to this: router.Any("/echo", echo.WrapHandler(websocketServer), deleteOrigin)
@kataras I have another problem with sockets, the socket is disconnect and reconnect a lot of times and i don't know why
Hello @xXLokerXx, is this the neffos.js javascript client library? If so please check the reconnect option and try to remove it or increase its value. Neffos is trying to re-connect on networks errors (in browser and nodejs client). Is this a backend (main neffos websocket server) issue? Do you have a code I can take a look of?
Thanks,
@kataras yes i've working with neffos.js and nefos (for go), i've got the next error:
goroutine 1272113 [running]:
runtime.throw(0xe3003b, 0x15)
/usr/local/go/src/runtime/panic.go:774 +0x72 fp=0xc0001a38e8 sp=0xc0001a38b8 pc=0x42f8d2
runtime.mapdelete_faststr(0xd1a2a0, 0xc0001d8120, 0xc0008a02ef, 0x2)
/usr/local/go/src/runtime/map_faststr.go:306 +0x386 fp=0xc0001a3950 sp=0xc0001a38e8 pc=0x414f36
github.com/server/socket.(*serverConn).OnNamespaceDisconnect(0xc000010148, 0x0, 0x0, 0xc000c401c0, 0x7, 0x0, 0x0, 0xe30ffd, 0x16, 0x0, ...)
/go/src/github.com/server/socket/socket.go:63 +0xe5 fp=0xc0001a39a8 sp=0xc0001a3950 pc=0x96cc95
runtime.call256(0xc0008253b0, 0xc0009d41f8, 0xc000930000, 0xb8000000c8)
/usr/local/go/src/runtime/asm_amd64.s:542 +0x55 fp=0xc0001a3ab8 sp=0xc0001a39a8 pc=0x45a3f5
reflect.callMethod(0xc007754bc0, 0xc0001a3b98, 0xc0001a3b80)
/usr/local/go/src/reflect/value.go:714 +0x1f0 fp=0xc0001a3b68 sp=0xc0001a3ab8 pc=0x48bf00
reflect.methodValueCall(0x0, 0x0, 0xc000c401c0, 0x7, 0x0, 0x0, 0xe30ffd, 0x16, 0x0, 0x0, ...)
/usr/local/go/src/reflect/asm_amd64.s:35 +0x42 fp=0xc0001a3b98 sp=0xc0001a3b68 pc=0x4957b2
github.com/kataras/neffos.makeEventFromMethod.func1(0xc0007a80c0, 0x0, 0x0, 0xc000c401c0, 0x7, 0x0, 0x0, 0xe30ffd, 0x16, 0x0, ...)
/go/src/github.com/kataras/neffos/reflect.go:208 +0xbf fp=0xc0001a3c68 sp=0xc0001a3b98 pc=0x95217f
github.com/kataras/neffos.Events.fireEvent(0xc0001d8180, 0xc0007a80c0, 0x0, 0x0, 0xc000c401c0, 0x7, 0x0, 0x0, 0xe30ffd, 0x16, ...)
/go/src/github.com/kataras/neffos/conn_handler.go:41 +0x16a fp=0xc0001a3d40 sp=0xc0001a3c68 pc=0x9469da
github.com/kataras/neffos.(*Conn).Close(0xc001394400)
/go/src/github.com/kataras/neffos/conn.go:1023 +0x1a8 fp=0xc0001a3f50 sp=0xc0001a3d40 pc=0x946658
github.com/kataras/neffos.(*Conn).startReader(0xc001394400)
/go/src/github.com/kataras/neffos/conn.go:335 +0x169 fp=0xc0001a3fd8 sp=0xc0001a3f50 pc=0x942419
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc0001a3fe0 sp=0xc0001a3fd8 pc=0x45bf41
created by github.com/kataras/neffos.(*Server).Upgrade
/go/src/github.com/kataras/neffos/server.go:340 +0x6c2
and i use the next code in backend:
package socket
import (
"fmt"
"log"
"net/http"
"github.com/kataras/neffos"
"github.com/kataras/neffos/gobwas"
"github.com/labstack/echo"
)
type serverConn struct {
*neffos.NSConn
}
var (
Clients = make(map[string]*serverConn)
websocketServer *neffos.Server
)
func init() {
controller := new(serverConn)
events := neffos.NewStruct(controller).
SetNamespace("default").
// This will convert the "OnChat" method to a "Chat" event instead.
SetEventMatcher(neffos.EventTrimPrefixMatcher("On"))
websocketServer = neffos.New(
gobwas.DefaultUpgrader,
// gorilla.DefaultUpgrader, /* DefaultGobwasUpgrader can be used too. */
// gorilla.Upgrader(gorillaWs.Upgrader{CheckOrigin: func(*http.Request) bool { return true }}),
events)
}
func SocketHandler(router *echo.Echo) {
websocketServer.IDGenerator = func(w http.ResponseWriter, r *http.Request) string {
if userID := r.Header.Get("idUser"); userID != "" {
return userID
}
return neffos.DefaultIDGenerator(w, r)
}
router.Any("/echo", echo.WrapHandler(websocketServer))
}
func (c *serverConn) OnNamespaceConnected(msg neffos.Message) error {
// ctx := websocket.GetContext(c.Conn)
fmt.Printf("%v\n", c.Conn.ID())
Clients[c.Conn.ID()] = c
log.Printf("[%s] connected to namespace [%s] with IP [%s]",
c.Conn, msg.Namespace)
return nil
}
func (c *serverConn) OnNamespaceDisconnect(msg neffos.Message) error {
log.Printf("[%s] disconnected from namespace [%s]", c.Conn, msg.Namespace)
delete(Clients, c.Conn.ID())
return nil
}
func (c *serverConn) OnRoomJoined(msg neffos.Message) error {
text := fmt.Sprintf("[%s] joined to room [%s].", c, msg.Room)
log.Printf("%s", text)
// notify others.
c.Conn.Server().Broadcast(c, neffos.Message{
Namespace: msg.Namespace,
Room: msg.Room,
Event: "Notify",
Body: []byte(text),
})
return nil
}
func (c *serverConn) OnChat(msg neffos.Message) error {
log.Printf("[%s] sent: %s", c.Conn, string(msg.Body))
c.Conn.Server().Broadcast(c.Conn, msg)
return nil
}
func (c *serverConn) OnNotification(msg neffos.Message) error {
log.Printf("[%s] sent: '%s' to Notification", c.Conn, string(msg.Body))
c.Conn.Server().Broadcast(c.Conn, msg)
return nil
}