A modern, fast and scalable websocket framework with elegant API written in Go

Overview

neffos chat example

build status report card view examples chat frontend pkg

About neffos

Neffos is a cross-platform real-time framework with expressive, elegant API written in Go. Neffos takes the pain out of development by easing common tasks used in real-time backend and frontend applications such as:

  • Scale-out using redis or nats*
  • Adaptive request upgradation and server dialing
  • Acknowledgements
  • Namespaces
  • Rooms
  • Broadcast
  • Event-Driven architecture
  • Request-Response architecture
  • Error Awareness
  • Asynchronous Broadcast
  • Timeouts
  • Encoding
  • Reconnection
  • Modern neffos API client for Browsers, Nodejs* and Go

Learning neffos

Qick View

Server

import (
    // [...]
    "github.com/kataras/neffos"
    "github.com/kataras/neffos/gorilla"
)

func runServer() {
    events := make(neffos.Namespaces)
    events.On("/v1", "workday", func(ns *neffos.NSConn, msg neffos.Message) error {
        date := string(msg.Body)

        t, err := time.Parse("01-02-2006", date)
        if err != nil {
            if n := ns.Conn.Increment("tries"); n >= 3 && n%3 == 0 {
                // Return custom error text to the client.
                return fmt.Errorf("Why not try this one? 06-24-2019")
            } else if n >= 6 && n%2 == 0 {
                // Fire the "notify" client event.
                ns.Emit("notify", []byte("What are you doing?"))
            }
            // Return the parse error back to the client.
            return err
        }

        weekday := t.Weekday()

        if weekday == time.Saturday || weekday == time.Sunday {
            return neffos.Reply([]byte("day off"))
        }

        // Reply back to the client.
        responseText := fmt.Sprintf("it's %s, do your job.", weekday)
        return neffos.Reply([]byte(responseText))
    })

    websocketServer := neffos.New(gorilla.DefaultUpgrader, events)

    // Fire the "/v1:notify" event to all clients after server's 1 minute.
    time.AfterFunc(1*time.Minute, func() {
        websocketServer.Broadcast(nil, neffos.Message{
            Namespace: "/v1",
            Event:     "notify",
            Body:      []byte("server is up and running for 1 minute"),
        })
    })

    router := http.NewServeMux()
    router.Handle("/", websocketServer)

    log.Println("Serving websockets on localhost:8080")
    log.Fatal(http.ListenAndServe(":8080", router))
}

Go Client

func runClient() {
    ctx := context.TODO()
    events := make(neffos.Namespaces)
    events.On("/v1", "notify", func(c *neffos.NSConn, msg neffos.Message) error {
        log.Printf("Server says: %s\n", string(msg.Body))
        return nil
    })

    // Connect to the server.
    client, err := neffos.Dial(ctx,
        gorilla.DefaultDialer,
        "ws://localhost:8080",
        events)
    if err != nil {
        panic(err)
    }

    // Connect to a namespace.
    c, err := client.Connect(ctx, "/v1")
    if err != nil {
        panic(err)
    }

    fmt.Println("Please specify a date of format: mm-dd-yyyy")

    for {
        fmt.Print(">> ")
        var date string
        fmt.Scanf("%s", &date)

        // Send to the server and wait reply to this message.
        response, err := c.Ask(ctx, "workday", []byte(date))
        if err != nil {
            if neffos.IsCloseError(err) {
                // Check if the error is a close signal,
                // or make use of the `<- client.NotifyClose`
                // read-only channel instead.
                break
            }

            // >> 13-29-2019
            // error received: parsing time "13-29-2019": month out of range
            fmt.Printf("error received: %v\n", err)
            continue
        }

        // >> 06-29-2019
        // it's a day off!
        //
        // >> 06-24-2019
        // it's Monday, do your job.
        fmt.Println(string(response.Body))
    }
}

Javascript Client

Navigate to: https://github.com/kataras/neffos.js

Neffos contains extensive and thorough wiki making it easy to get started with the framework.

For a more detailed technical documentation you can head over to our godocs. And for executable code you can always visit the _examples repository's subdirectory.

Do you like to read while traveling?

You can request a PDF version of the E-Book today and be participated in the development of neffos.

https://iris-go.com/images/neffos-book-overview.png

Contributing

We'd love to see your contribution to the neffos real-time framework! For more information about contributing to the neffos project please check the CONTRIBUTING.md file.

  • neffos-contrib github organisation for more programming languages support, please invite yourself.

Security Vulnerabilities

If you discover a security vulnerability within neffos, please send an e-mail to [email protected]. All security vulnerabilities will be promptly addressed.

License

The word "neffos" has a greek origin and it is translated to "cloud" in English dictionary.

This project is licensed under the MIT license.

Comments
  • [Question\Websocket] How to send binary data with neffos(websocket)?

    [Question\Websocket] How to send binary data with neffos(websocket)?

    #387 I have read this issue. But cannot found, websocket.Config

    Then i found that, Iris websocket library is now merged with the neffos real-time framework But i cann't find a correct way to send binary data with neffos.

    Is there any config for neffos to send binary instead of string?

    opened by StartAt24 13
  • Problem with Broadcasting

    Problem with Broadcasting

    @kataras I have Issue with

    server.Broadcast(nil,neffos.Message{
    To: userID,
    Namespace: variable.Agent,
    Event:     "notif",
    Body:      neffos.Marshal(nf),	
    })
    

    i use gobwas.DefaultUpgrader

    when i use server.Broadcast in loop it is work but But not very good. You can test yourself. i open multiple browser tap with same userId(socketId)

    server.brodacast not send all message in loop;

    you can see cron example .

    c.write(neffos.Message{
    To: userID,
    Namespace: variable.Agent,
    Event:     "notif",
    Body:      neffos.Marshal(nf),	
    })
    
    

    write() mthod work very very good but it send message to one tap (last) with same userId .

    I'm going to send it to all the tabs. with same userId

    opened by majidbigdeli 12
  • Problem with CORS and websockets

    Problem with CORS and websockets

    Describe the bug I have an issue with cors, when i run it the example in 2 diferents ports (3000, 3001) and i try to conect a new socket from 3001 to 3000 then the console throw the next error: WebSocket connection to 'ws://localhost:3001/echo?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjozMjEzMjF9.8waEX7-vPKACa-Soi1pQvW3Rl8QY-SUFcHKTLZI4mvU' failed: Error during WebSocket handshake: Unexpected response code: 403.

    To Reproduce Use the example server.go on the route: _examples/websocket/basic/

    package main
    
    import (
    	"log"
    
    	"github.com/kataras/iris"
    	"github.com/kataras/iris/websocket"
    
    	// Used when "enableJWT" constant is true:
    	"github.com/iris-contrib/middleware/jwt"
    )
    
    // values should match with the client sides as well.
    const enableJWT = true
    const namespace = "default"
    
    // 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)
    
    			log.Printf("[%s] connected to namespace [%s] with IP [%s]",
    				nsConn, msg.Namespace,
    				ctx.RemoteAddr())
    			return nil
    		},
    		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 *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))
    
    			// Write message back to the client message owner with:
    			// nsConn.Emit("chat", msg)
    			// Write message to all except this client with:
    			nsConn.Conn.Server().Broadcast(nsConn, msg)
    			return nil
    		},
    	},
    }
    
    func main() {
    	app := iris.New()
    	websocketServer := websocket.New(
    		websocket.DefaultGorillaUpgrader, /* DefaultGobwasUpgrader can be used too. */
    		serverEvents)
    
    	j := jwt.New(jwt.Config{
    		// Extract by the "token" url,
    		// so the client should dial with ws://localhost:8080/echo?token=$token
    		Extractor: jwt.FromParameter("token"),
    
    		ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
    			return []byte("My Secret"), nil
    		},
    
    		// When set, the middleware verifies that tokens are signed
    		// with the specific signing algorithm
    		// If the signing method is not constant the
    		// `Config.ValidationKeyGetter` callback field can be used
    		// to implement additional checks
    		// Important to avoid security issues described here:
    		// https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
    		SigningMethod: jwt.SigningMethodHS256,
    	})
    
    	idGen := func(ctx iris.Context) string {
    		if username := ctx.GetHeader("X-Username"); username != "" {
    			return username
    		}
    
    		return websocket.DefaultIDGenerator(ctx)
    	}
    
    	// serves the endpoint of ws://localhost:8080/echo
    	// with optional custom ID generator.
    	websocketRoute := app.Get("/echo", websocket.Handler(websocketServer, idGen))
    
    	if enableJWT {
    		// Register the jwt middleware (on handshake):
    		websocketRoute.Use(j.Serve)
    		// OR
    		//
    		// Check for token through the jwt middleware
    		// on websocket connection or on any event:
    		/* 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
    			// and will not allow it to connect to the websocket server at all.
    			return err
    		}
    
    		user := ctx.Values().Get("jwt").(*jwt.Token)
    		// or just: user := j.Get(ctx)
    
    		log.Printf("This is an authenticated request\n")
    		log.Printf("Claim content:")
    		log.Printf("%#+v\n", user.Claims)
    
    		log.Printf("[%s] connected to the server", c.ID())
    
    		return nil
    		} */
    	}
    
    	// serves the browser-based websocket client.
    	app.Get("/", func(ctx iris.Context) {
    		ctx.ServeFile("./browser/index.html", false)
    	})
    
    	// serves the npm browser websocket client usage example.
    	app.HandleDir("/browserify", "./browserify")
    
    	app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
    }
    

    Expected behavior I would like to make petitions from the 2 servers

    Posible fix To catch this i made a middleware function wich delete the origin header (but this will be a rellay bad practice), code above:

            app.Use(func(ctx iris.Context) {
    		ctx.Request().Header.Del("Origin")
    		ctx.Next()
    	})
    
    opened by xXLokerXx 9
  • [BUG] the neffos server hang up whole goroutines

    [BUG] the neffos server hang up whole goroutines

    Describe the bug After upgrade lastest version, it still happened on productions. Debugging by dlv tool, I found the neffos block whole process.

    Screenshots 4011585729190_ pic_hd 4021585729215_ pic_hd

    Desktop (please complete the following information):

    • OS: Centos
    • Version 7.7

    Could you have time to handle this questions?

    bug pending-submitter-response 
    opened by LeeEirc 7
  • [BUG] the process hang up, CPU become 100%

    [BUG] the process hang up, CPU become 100%

    Describe the bug

    I use neffos as WebSocket server to handler all WebSocket connects from browser. It is running well when first deploy the web Application on production server. However it became weird at some moment. The CPU became 100% usage, and the server could not handle any incoming WebSocket connection. Debugging by dlv tool, I found the neffos conn's goroutine block main process. I don't know how reproduce this bug, but it happened several times on productions environment.

    To Reproduce

    Expected behavior I hope how to avoid this situation or this is the bug.

    Screenshots image

    image

    Desktop (please complete the following information):

    • OS: Centos
    • Version 7
    opened by LeeEirc 3
  •   在v12版本中,neffos的websocket在前后端分离的情况下提示403 In v12 version, the websocket of neffos prompts 403 when the front and back ends are separated

    在v12版本中,neffos的websocket在前后端分离的情况下提示403 In v12 version, the websocket of neffos prompts 403 when the front and back ends are separated

    WebSocket connection to 'ws://127.0.0.1:8888/echo?X-Websocket-Header-X-Username=yhm' failed: Error during WebSocket handshake: Unexpected response code: 403

    opened by mualala 3
  • Can you provide more programming language examples

    Can you provide more programming language examples

    I just use example in https://github.com/kataras/iris/blob/master/_examples/websocket/basic/server.go

    After run this server, I cannot access from python script.

    The Python Script:

    from websocket import create_connection
    ws = create_connection("ws://127.0.0.1:8080/echo?X-Websocket-Header-X-Username=ok&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjozMjEzMjF9.8waEX7-vPKACa-Soi1pQvW3Rl8QY-SUFcHKTLZI4mvU")
    print("Sending 'Hello, World'...")
    ws.send("Hello, World")
    print("Sent")
    print("Receiving...")
    result =  ws.recv()
    print("Received '%s'" % result)
    ws.close()
    

    And the result shows that script can establish a connection, but when the client begins to receive , it shows that "WebSocketConnectionClosedException: Connection is already closed."

    This problem also happens when I serve "./broswer/index.html" at another port using another web quick server (the index.html file has been modified so that the websocket port is still the same as server-side, that is, 8080.), it shows that

    neffos.min.js:1 WebSocket connection to 'ws://0.0.0.0:8080/echo?X-Websocket-Header-X-Username=jhi&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjozMjEzMjF9.8waEX7-vPKACa-Soi1pQvW3Rl8QY-SUFcHKTLZI4mvU' failed: Error during WebSocket handshake: Unexpected response code: 403
    

    So what should I do? And can you help me with a python websocket client script? Because I will use python script to listen and handle the websocket broadcasting message. Thank you.

    enhancement 
    opened by BuGTEa 3
  • [BUG]Binary data contains

    [BUG]Binary data contains ";" will be droped!

    Sorry to bother you. But i have found the bug. It is in neffos.js.

    I'm using protobuf with neffos.js. The data that protobuf make counld contain ;. So that my message will be drop in neffos.js in here.

      var isArrayBuffer = data instanceof ArrayBuffer;
        var dts;
    
        console.log(isArrayBuffer)
    
        if (isArrayBuffer) {
            var arr = new Uint8Array(data);
            var sepCount = 1;
            var lastSepIndex = 0;
            for (var i = 0; i < arr.length; i++) {
                if (arr[i] == messageSeparatorCharCode) { // sep char.
                    sepCount++;
                    lastSepIndex = i;
                }
            }
           // Drop here!!!!!!!!!!!!
            if (sepCount != validMessageSepCount) {
                msg.isInvalid = true;
                console.log("return at validMessageSepCount")
                return msg;
            }
            dts = splitN(textDecoder.decode(arr.slice(0, lastSepIndex)), messageSeparator, validMessageSepCount - 2);
            dts.push(data.slice(lastSepIndex + 1, data.length));
            msg.SetBinary = true;
        }
        else {
            dts = splitN(data, messageSeparator, validMessageSepCount - 1);
        }
    

    I thank it is a bug. Cannot just split message by ;.

    Here is the reproducible code.

    Server

    package main
    
    import (
    	"github.com/kataras/iris"
    	"fmt"
    	"github.com/kataras/iris/websocket"
    	"github.com/kataras/neffos"
    	"time"
    )
    
    // 全局变量
    var page = struct {
        Title string
    }{"Collector"}
    
    func main(){
    	app := iris.New()
    
    	ws_server := startWebSocketServer(app)
    
    	go pub_thread(ws_server)
    
    	app.RegisterView(iris.HTML("./static", ".html"))
    	app.Get("/" ,func(ctx iris.Context){
    		ctx.ViewData("Page", page)
    		ctx.View("index.html")
    	})
    
    	app.HandleDir("/", "./static")	
        app.Run(iris.Addr(":5000"), iris.WithoutPathCorrection)
    }
    
    var serverEvents = websocket.Namespaces{
    	"default": 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)
    
    			fmt.Printf("[%s] connected to namespace [%s] with IP [%s]\n",
    				nsConn, msg.Namespace,
    				ctx.RemoteAddr())
    			return nil
    		},
    		websocket.OnNamespaceDisconnect: func(nsConn *websocket.NSConn, msg websocket.Message) error {
    			fmt.Printf("[%s] disconnected from namespace [%s]\n", nsConn, msg.Namespace)
    			return nil
    		},
    		"stream": func(nsConn *websocket.NSConn, msg websocket.Message) error {
    			// room.String() returns -> NSConn.String() returns -> Conn.String() returns -> Conn.ID()
    			fmt.Printf("[%s] sent: %s", nsConn, string(msg.Body))
    
    			// Write message back to the client message owner with:
    			// nsConn.Emit("chat", msg)
    			// Write message to all except this client with:
    			nsConn.Conn.Server().Broadcast(nsConn, msg)
    			return nil
    		},
    	},
    }
    
    func startWebSocketServer(app *iris.Application) *neffos.Server{
    	server := websocket.New(websocket.DefaultGorillaUpgrader, serverEvents)
    	server.OnConnect = func(c *websocket.Conn) error {
    		fmt.Printf("[%s] connected to the server.\n", c)
    		
    		return nil
    	}
    
    	server.OnDisconnect = func(c *websocket.Conn){
    		fmt.Printf("[%s] disconnected from the server.", c)
    	}
    
    	fmt.Printf("Listening on: %d\nPress CTRL/CMD+C to interrupt.\n", 5000)
    
    	idGen := func(ctx iris.Context) string {
    		if username := ctx.GetHeader("X-Username"); username != "" {
    			return username
    		}
    
    		return websocket.DefaultIDGenerator(ctx)
    	}
    
    	app.Get("/stream", websocket.Handler(server, idGen))
    
    	return server
    }
    
    func pub_thread(serve *neffos.Server){
    	png:= [...] byte{';',';',';',';',';'}
    	slice := png[:]
    	for{
    		serve.Broadcast(nil, neffos.Message{SetBinary: true,  Body:slice, Namespace: "default"})
    		time.Sleep(1*time.Second)
    	}
    }
    

    Client

    <html>
        <button> useless button</button>
    
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/neffos.js"></script>
        <script>
        
            var scheme = document.location.protocol == "https:" ? "wss" : "ws";
            var port = document.location.port ? ":" + document.location.port : "";
            var wsURL = scheme + "://" + document.location.hostname + port + "/stream";
            
            function handleError(reason) {
                console.log(reason);
            }
            
            function handleNamespaceConnectedConn(nsConn) {
    
            }
            // const username = window.prompt("Your username?");
            async function runExample() {
                // You can omit the "default" and simply define only Events, the namespace will be an empty string"",
                // however if you decide to make any changes on this example make sure the changes are reflecting inside the ../server.go file as well.
                try {
                    const conn = await neffos.dial(wsURL, {
                        default: { // "default" namespace.
                            _OnNamespaceConnected: function (nsConn, msg) {
                                handleNamespaceConnectedConn(nsConn)
                            },
                            _OnNamespaceDisconnect: function (nsConn, msg) {
                            },
                            stream: function (nsConn, msg) { // "stream" event.
                                console.log(msg.Body);
                                console.log(msg)
                            }
                        }
                    },{
                        headers: {
                            "X-Username": "",
                        }
                    });
                    // You can either wait to conenct or just conn.connect("connect")
                    // and put the `handleNamespaceConnectedConn` inside `_OnNamespaceConnected` callback instead.
                    // const nsConn = await conn.connect("default");
                    // nsConn.emit(...); handleNamespaceConnectedConn(nsConn);
                    conn.connect("default");
                } catch (err) {
                    handleError(err);
                }
            }
    
            runExample()
        </script>
    </html>
    
    bug 
    opened by StartAt24 3
  • Is neffos.Conn.Socket().WriteText() Atomic?

    Is neffos.Conn.Socket().WriteText() Atomic?

    If I start several goroutines calling neffos.Conn.Socket().WriteText(text, timeout) concurrently, would the texts be blended? Thanks for your attention!

    opened by Rossil2012 2
  • Hello, excuse me, I want to transfer my application to neffos. How does neffos send messages to websocket thread in web thread? Just like the socket.io-emitter package of node.js socketio

    Hello, excuse me, I want to transfer my application to neffos. How does neffos send messages to websocket thread in web thread? Just like the socket.io-emitter package of node.js socketio

    Hello, excuse me, I want to transfer my application to neffos. How does neffos send messages to websocket thread in web thread? Just like the socket.io-emitter package of node.js socketio

    opened by ezewu 2
  • [question] Why brower loop print re-connected and send head endpoint request?

    [question] Why brower loop print re-connected and send head endpoint request?

    I'm use neffos.js code :

    image

    But i'm find console loop print re-connected , time is i'm set reconnect , This is keeplive?

    image

    And find console print send HEAD methods to set endpoint , I'm set iris to Any but is not work

    image

    The Head request how to success?

    I'm client how to keeplive? if use reconnect , I'm iris log all reconnected log , is not good~

    thanks for help ~ @kataras

    opened by 23233 2
  • Bump github.com/nats-io/nats.go from 1.19.0 to 1.20.0

    Bump github.com/nats-io/nats.go from 1.19.0 to 1.20.0

    Bumps github.com/nats-io/nats.go from 1.19.0 to 1.20.0.

    Release notes

    Sourced from github.com/nats-io/nats.go's releases.

    Release v1.20.0

    Changelog

    Changed

    • JetStream:
      • [BREAKING CHANGE] Extract nats: Consumer Deleted server error to ErrConsumerDeleted variable. This error is returned when consumer is deleted while waiting on pull request and was introduced in nats-server v2.9.6 (#1125)

    Improved

    • JetStream:
      • Fix broken comments on ErrConsumerNameAlreadyInUse and StreamNameBySubject(). Thanks to @​subtle-byte for the contribution (#1128)
    • Core NATS:
      • Improve comment on RetryOnFailedConnect connect option (#1127)

    Complete Changes

    https://github.com/nats-io/nats.go/compare/v1.19.1...v1.20.0

    Release v1.19.1

    Changelog

    Added

    • JetStream:
      • Expose StreamNameBySubject method on JetStreamContext interface for looking up stream by subject (#1114)
      • Return stream alternates when fetching stream info (#1118)

    Changed

    • KV:
      • Use BindStream for watcher so it works with mirrors (#1116)

    Fixed

    • KV:
      • Delete key not working correctly across mirrors (#1115)

    Complete Changes

    https://github.com/nats-io/nats.go/compare/v1.19.0...v1.19.1

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 0
  • How to assign some values to a socket connection?

    How to assign some values to a socket connection?

    Is there any option to assign some values to socket (like in node.js web socket )?When a client is connected, we can set some room id , seat id and status to socket and check its value when its disconnected or sending any messages.

    like socket.status = "connected" socket.room_id = "room1" socket.seat_id = "seat1"

    enhancement 
    opened by Swaraj-cs 0
  • how to react on native mode when a client or a server disconnected

    how to react on native mode when a client or a server disconnected

    as the title,when i connect to server with native mode (because server is not golang),so i can implement it as https://github.com/kataras/neffos/wiki/Native-messages,but now i wanna know how can i know that the server is disconnected,thank you

    enhancement 
    opened by Nyx2022 0
  • [BUG] basic in example, broswer message must be sent twice

    [BUG] basic in example, broswer message must be sent twice

    Describe the bug ① in app.js 45line toId is not defined! ②using example basic, broswer every send message need two times it worked, why it happend? server only recived An odd number of times message,the phenomena is every stable

    Note that if a bug is a browser-relative please report it at the neffos.js repository instead. Thanks! chrome and firefox

    To Reproduce Steps to reproduce the behavior: reproduce:https://github.com/kataras/neffos/tree/master/_examples/basic

    bug 
    opened by Iteravse 0
  • [BUG] Broadcast deadlocks when concurrency

    [BUG] Broadcast deadlocks when concurrency

    Describe the bug I found in the actual application that the Broadcast() method will cause a deadlock

    To Reproduce Steps to reproduce the behavior:

    1. When nsConn is disconnected, it will cause Server.Broadcast() internal blocking'' when broadcasting a message on the websocket.OnNamespaceDisconnect or websocket.OnRoomLeft event
    2. code
    package main
    
    import (
    	"fmt"
    	gorilla "github.com/gorilla/websocket"
    	"github.com/kataras/iris/v12"
    	"github.com/kataras/iris/v12/websocket"
    	"github.com/kataras/neffos"
    	"net/http"
    	"time"
    )
    
    func main() {
    	namespace, room, event := "test", "ttt", "ch"
    	chatServer := websocket.New(
    		websocket.GorillaUpgrader(gorilla.Upgrader{
    			ReadBufferSize:  1024,
    			WriteBufferSize: 1024,
    			// todo 允许所有的CORS 跨域请求,正式环境可以关闭
    			CheckOrigin: func(r *http.Request) bool {
    				return true
    			},
    		}),
    		websocket.WithTimeout{
    			WriteTimeout: time.Second * 60,
    			ReadTimeout:  time.Second * 60,
    			Namespaces: websocket.Namespaces{
    				namespace: websocket.Events{
    					websocket.OnNamespaceConnected: func(nsConn *websocket.NSConn, msg websocket.Message) error {
    						fmt.Println("OnNamespaceConnected", nsConn.Conn.ID())
    						nsConn.JoinRoom(nil, room)
    						return nil
    					},
    					websocket.OnNamespaceDisconnect: func(nsConn *websocket.NSConn, msg websocket.Message) error {
    						fmt.Println("OnNamespaceDisconnect", nsConn.Conn.ID())
    						// Todo The broadcast here will cause blocking in `server.start()`
    						//nsConn.Conn.Server().Broadcast(nsConn, neffos.Message{
    						//	Body:      []byte("我离开了room" + nsConn.Conn.ID()),
    						//	Namespace: namespace,
    						//	Room:      room,
    						//	To:        "",
    						//	Event:     event,
    						//})
    
    						// Todo Add a certain delay and everything is normal
    						time.AfterFunc(time.Millisecond*50, func() {
    							nsConn.Conn.Server().Broadcast(nsConn, neffos.Message{
    								Body:      []byte("我离开了room" + nsConn.Conn.ID()),
    								Namespace: namespace,
    								Room:      room,
    								To:        "",
    								Event:     event,
    							})
    						})
    
    						return nil
    					},
    					websocket.OnRoomJoined: func(nsConn *websocket.NSConn, msg websocket.Message) error {
    						fmt.Println("OnRoomJoined", nsConn.Conn.ID())
    						nsConn.Emit(event, []byte("我是单独消息"))
    						nsConn.Conn.Server().Broadcast(nil, neffos.Message{
    							Body:      []byte("我加入了room" + nsConn.Conn.ID()),
    							Namespace: namespace,
    							Room:      room,
    							To:        "",
    							Event:     event,
    						})
    
    						return nil
    					},
    					websocket.OnRoomLeft: func(nsConn *websocket.NSConn, msg websocket.Message) error {
    						fmt.Println("OnRoomLeft", nsConn.Conn.ID(), nsConn.Conn.IsClosed())
    						// Todo The broadcast here will cause blocking in `server.start()`
    						//nsConn.Conn.Server().Broadcast(nsConn, neffos.Message{
    						//	Body:      []byte("我离开了room" + nsConn.Conn.ID()),
    						//	Namespace: namespace,
    						//	Room:      room,
    						//	To:        "",
    						//	Event:     event,
    						//})
    
    						// Todo Add a certain delay and everything is normal
    						time.AfterFunc(time.Millisecond*50, func() {
    							nsConn.Conn.Server().Broadcast(nsConn, neffos.Message{
    								Body:      []byte("我离开了room" + nsConn.Conn.ID()),
    								Namespace: namespace,
    								Room:      room,
    								To:        "",
    								Event:     event,
    							})
    						})
    						return nil
    					},
    				},
    			},
    		},
    	)
    
    	app := iris.New()
    	app.Get("/e", websocket.Handler(chatServer, func(ctx iris.Context) string {
    		return ctx.URLParam("id")
    	}))
    
    	// Todo If you don't want to lose messages, please turn it on
    	chatServer.SyncBroadcaster = true
    
    	app.Listen("0.0.0.0:8090")
    }
    
    
    
    bug 
    opened by AlanTianx 2
Releases(v0.0.20)
  • v0.0.20(Jul 17, 2022)

  • v0.0.18(Nov 17, 2020)

  • v0.0.16(May 18, 2020)

    Add 'Server.FireDisconnectAlways' option to enable calling the local OnDisconnectevent if the server closed the connection from itsOnConnect` event, as requested at: #41

    Source code(tar.gz)
    Source code(zip)
  • v0.0.15(Apr 28, 2020)

  • v0.0.14(Feb 11, 2020)

  • v0.0.12(Dec 10, 2019)

  • v0.0.11(Dec 10, 2019)

    • fix https://github.com/kataras/neffos/issues/20
    • give more respect to the Message.SetBinary
    • set Message.SetBinary for incoming messages using the operation code that the lower level protocol gave us

    Relative: https://github.com/kataras/neffos.js/commit/b5a916ec41193f320d5bcd276598e2e5ecfc795c

    Source code(tar.gz)
    Source code(zip)
  • v0.0.10(Aug 10, 2019)

    Contains two fixes

    1. Fix Server.Broadcast call inside Server.OnConnect callback when Server.UseStackExchange is used.
    2. Add Server.SyncBroadcaster which, if set to true, changes the default behavior and sync Server.Broadcast calls when Server.StackExchange is nil (or Server.UseStackExchange is not used). When StackExchange is used then this field is ignored, published messages were correctly handled by Redis or Nats already.
    Source code(tar.gz)
    Source code(zip)
  • v0.0.9(Aug 3, 2019)

  • v0.0.8(Jul 19, 2019)

    • Add On helper method on Events and Namespaces.
    • Make NSConn.JoinRoom and LeaveRoom to work synchronously inside event message handlers/callbacks.
    • Exports the Subject prefix of the stackexchange/nats.
    Source code(tar.gz)
    Source code(zip)
  • v0.0.7(Jul 14, 2019)

    • Add support for scaling-out using Nats with the stackexchange/nats subpackage, among with Redis from previous version.
    • Add support to register many StackExchanges.
    • Implement a Server.Ask which will block until/wait for a response from a specific client if msg.To is filled or from the first responder from either the cloud(if StackExchange is used) or from this server instance's connected clients, ofc you should still use the Conn.Ask if you know the client to ask from.
    • Update gobwas/ws dependency.

    Commits log:

    • https://github.com/kataras/neffos/compare/v0.0.6...v0.0.7
    Source code(tar.gz)
    Source code(zip)
  • v0.0.6(Jul 11, 2019)

    Add support for scaling-out with 3 lines of code. A new interface type of StackExchange is created and it's used on server and server connections if registered through Server.StackExchange field. A built-in redis StackExchange using a lightweight library is available for use.

    Example:

    • https://github.com/kataras/neffos/tree/master/_examples/redis
    import "github.com/kataras/neffos/stackexchange/redis"
    
    // [server := neffos.New...]
    
    exc, err := redis.NewStackExchange(redis.Config{}, "MyChatApp")
    if err != nil {
    	// [...]
    }
    server.StackExchange = exc
    

    Critical Commits:

    • https://github.com/kataras/neffos/commit/4de9b6608fc914beceeb7eedbd2ab1680635b094

    Request by:

    • https://github.com/kataras/neffos/issues/3
    Source code(tar.gz)
    Source code(zip)
  • v0.0.5(Jul 9, 2019)

    Export the ability of custom ConnHandlers and a lot of improvements that allow external packages to interact with the (NewStruct) feature, an example of this is the Iris' new v11.2+ fully featured MVC websocket controller.

    Minimum Go Installed required version is set to 1.12.

    Critical commits:

    • https://github.com/kataras/neffos/commit/26005b6ec445554c1155d1373a3605e23ad16c55
    • https://github.com/kataras/iris/commit/ab321a602639c7fcfde51bed7315cfbf8cdbb112
    Source code(tar.gz)
    Source code(zip)
  • v0.0.4(Jul 7, 2019)

    Improvements of the neffos.NewStruct connection handler.

    • With the new EnableDebug(nil_or_custom_printer) the neffos.NewStruct will log which field is marked as static, which method is handling a specific event and etc.
    • A new method Events() neffos.Events is added to the return value of the neffos.NewStruct in order to handle that struct as raw neffos.Events - this adds support to wrap one or more "controllers" on a neffos.Namespaces or neffos.WithTimeout connection handler. Note that when Events() is used then its SetNamespace and SetTimeouts have no effect because they should be handled by the parent level instead.

    Example Code:

    var events = neffos.Namespaces{
        "ns1": neffos.NewStruct(new(myWebsocketController)).Events(),
        "ns2": neffos.Events{...},
    }
    

    Have fun!

    Source code(tar.gz)
    Source code(zip)
  • v0.0.3(Jul 5, 2019)

    Add a neffos.NewStruct to convert struct's methods to events. Read more at: https://github.com/kataras/neffos/wiki/Getting-started#using-a-struct-value

    And add a customID string input argument to the neffos.Upgrade which iris is using to make it compatible. The neffos users can use the whole Server as a http.Handler through its ServeHTTP method ofc.

    Source code(tar.gz)
    Source code(zip)
  • v0.0.2(Jun 30, 2019)

Owner
Gerasimos (Makis) Maropoulos
🥇 That Greek Gopher | 💨 Senior Backend Engineer at PNOĒ | 🎓My dream is to create an international IT university that will produce flawless developers!
Gerasimos (Makis) Maropoulos
Encrypted-websocket-chat - Encrypted websocket chat using golang

Encrypted websocket chat First version written in python This version should be

Artyom Artamonov 13 Sep 15, 2022
Websocket-chat - A simple websocket chat application

WebSocket Chat App This is a simple chat app based on websockets. It allows user

null 1 Jan 25, 2022
A fast, well-tested and widely used WebSocket implementation for Go.

Gorilla WebSocket Gorilla WebSocket is a Go implementation of the WebSocket protocol. Documentation API Reference Chat example Command example Client

Gorilla Web Toolkit 18.4k Nov 21, 2022
:notes: Minimalist websocket framework for Go

melody ?? Minimalist websocket framework for Go. Melody is websocket framework based on github.com/gorilla/websocket that abstracts away the tedious p

Ola 2.6k Nov 22, 2022
Comet - Minimalist websocket framework for Go

Comet : fork Melody ?? Minimalist websocket framework for Go. Comet is websocket

tommy 1 Feb 8, 2022
API that upgrades connection to use websocket. Contains server and client and testing how they communicate

Websocket Test API How to execute First run server using: make run-server. Then run many client instances with: make run-client. Then start typing in

null 0 Dec 25, 2021
Websocket server. Get data from provider API, clean data and send to websoket, when it's changed.

Описание Сервис получает данные по киберспортивным матчам CS:GO от провайдера, структурирует, очищает от лишнего и отправляет всем активным вебсокет к

null 1 Apr 6, 2022
WebSocket Command Line Client written in Go

ws-cli WebSocket Command Line Client written in Go Installation go get github.com/kseo/ws-cli Usage $ ws-cli -url ws://echo.websocket.org connected (

Kwang Yul Seo 17 Nov 12, 2021
A tiny command line websocket client written in Go

wsc A simplistic tool for sending and receiving websocket messages from a command line. Mainly useful to test websocket servers. Getting started: $ go

Raphael Simon 49 Jan 12, 2022
A websocket powered telegram wrapper for Sugaroid written in golang

sg-telegram A thin telegram wrapper built on top of Sugaroid Websocket

The Sugaroid Project 0 Nov 4, 2021
A websocket powered discord wrapper for Sugaroid written in golang

sg-discord A thin discord wrapper built on top of Sugaroid Websocket implementation. Build go build . Run export DISCORD_BOT_TOKEN="supersecrettoken"

The Sugaroid Project 0 Dec 30, 2021
Websocket market data capture utility for coinbase (written in Go)

mdcapture Websocket market data capture utility for coinbase (written in Go) Features Live subscription and capture of Coinbase market data Intended f

null 0 Jan 6, 2022
Websocket API Gateway that allows to subscribe on notifications about price changes of financial instruments

websocket-api-gateway Websocket API Gateway that allows to subscribe on notifications about price changes of financial instruments To test connection

null 1 Dec 5, 2021
Minimal and idiomatic WebSocket library for Go

websocket websocket is a minimal and idiomatic WebSocket library for Go. Install go get nhooyr.io/websocket Highlights Minimal and idiomatic API First

Anmol Sethi 2.4k Nov 16, 2022
Go-distributed-websocket - Distributed Web Socket with Golang and Redis

go-distributed-websocket Distributed Web Socket with Golang and Redis Dependenci

Filipe Alves 14 Oct 13, 2022
Turn any program that uses STDIN/STDOUT into a WebSocket server. Like inetd, but for WebSockets.

websocketd websocketd is a small command-line tool that will wrap an existing command-line interface program, and allow it to be accessed via a WebSoc

Joe Walnes 16.5k Nov 19, 2022
proxy your traffic through CDN using websocket

go-cdn2proxy proxy your traffic through CDN using websocket what does it do example server client thanks what does it do you can use this as a library

jm33-ng 42 Nov 15, 2022
Chat bots (& more) for Zoom by figuring out their websocket protocol

zoomer - Bot library for Zoom meetings Good bot support is part of what makes Discord so nice to use. Unfortunately, the official Zoom API is basicall

Christopher Tarry 49 Nov 19, 2022
Tiny WebSocket library for Go.

RFC6455 WebSocket implementation in Go.

Sergey Kamardin 4.8k Nov 27, 2022