Skip to content

Native messages

Gerasimos (Makis) Maropoulos edited this page Jun 29, 2019 · 4 revisions

When app expects to accept and send only raw/native websocket messages almost all features of neffos are disabled because no custom message format can pass the "ack" step.

When only allow native messages is a fact?

  • When the registered namespace is just one and it's empty and contains only one registered event which is the OnNativeMessage.
    • When Events{...} is used instead of Namespaces{ "namespaceName": Events{...}} then the namespace is empty "".

Native messages event can be used side by side with any other event if the application expects some clients to make use of neffos and some others to use the native websocket API provided by browsers and software libraries. However, it's not recommended to enable this feature unless it's really necessary, you use neffos for its features and performance, otherwise why bother?

Let's start by creating a simple websocket client using just the browser's websocket API.

<html>

<body style="padding:10px;">
    <input type="text" id="messageTxt" />
    <button type="button" id="sendBtn">Send</button>
    <div id="messages" style="width: 375px;margin:10 0 0 0px;border-top: 1px solid black;">
    </div>

    <script type="text/javascript">
        var messageTxt = document.getElementById("messageTxt");
        var messages = document.getElementById("messages");
        var sendBtn = document.getElementById("sendBtn")

        // You see? No neffos at all here.
        w = new WebSocket("ws://localhost:8080/endpoint");
        w.onopen = function () {
            console.log("Websocket connection enstablished");
        };
        w.onclose = function () {
            appendMessage("<div><center><h3>Disconnected</h3></center></div>");
        };
        w.onmessage = function (message) {
            appendMessage("<div>" + message.data + "</div>");
        };

        sendBtn.onclick = function () {
            myText = messageTxt.value;
            messageTxt.value = "";

            appendMessage("<div style='color: red'> me: " + myText + "</div>");
            w.send(myText);
        };

        messageTxt.addEventListener("keyup", function (e) {
            if (e.keyCode === 13) {
                e.preventDefault();

                sendBtn.click();
            }
        });

        function appendMessage(messageDivHTML) {
            messages.insertAdjacentHTML('afterbegin', messageDivHTML);
        }
    </script>
</body>

</html>

Enable native messages feature is done by defining a neffos.OnNativeMessage built-in event.

var pongMessage = []byte("pong")

var events = neffos.Events{
    neffos.OnNativeMessage: func(c *neffos.NSConn, msg neffos.Message) error {
        // ^^^^^^^^^^^^^^^
        log.Printf("Got: %s", string(msg.Body))

        if !c.Conn.IsClient() {
            return c.Conn.Socket().WriteText(pongMessage, 0)
            //                     ^^^^^^^^^
        }

        return nil
    },
}

Now let's make a neffos server that can accept and send to a client like the above.

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

    router := http.NewServeMux()
    router.Handle("/endpoint", websocketServer)
    router.Handle("/", http.FileServer(http.Dir("./browser")))

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

It's also possible to create a go-client side using any third-party websocket library or the standard net/x/websocket, however in this case we will create a neffos one:

func runClient() {
    ctx := context.Background()

    client, err := neffos.Dial(ctx,
        gorilla.DefaultDialer,
        "ws://localhost:8080/endpoint",
        events)

    if err != nil {
        panic(err)
    }

    // Connect does nothing at this case,
    // it just returns a connection to work with its methods.
    c, err := client.Connect(ctx, "")
    if err != nil {
        panic(err)
    }

    c.Conn.Socket().WriteText([]byte("ping"), 0)

    <-client.NotifyClose
}

The full source code of the example above is available at _examples/native-messages.