kataras/neffos.js

Can not we set the header in the dial?

Open

#1 opened on Jun 3, 2019

 (8 comments) (0 reactions) (0 assignees)TypeScript (16 forks)github user discovery
enhancementgood first issue

Repository metrics

Stars
 (40 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

I know that There is no method in the JavaScript WebSockets API for specifying additional headers for the client/browser to send. The HTTP path ("GET /xyz") and protocol header ("Sec-WebSocket-Protocol") can be specified in the WebSocket constructor.

The Sec-WebSocket-Protocol header (which is sometimes extended to be used in websocket specific authentication) is generated from the optional second argument to the WebSocket constructor:

var ws = new WebSocket("ws://example.com/path", "protocol");
var ws = new WebSocket("ws://example.com/path", ["protocol1", "protocol2"]);

The above results in the following headers: Sec-WebSocket-Protocol: protocol and Sec-WebSocket-Protocol: protocol1, protocol2

but I have error

WebSocket connection to 'ws://localhost:3811/echo' failed: Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received
(anonymous) @ neffos.js:612
dial @ neffos.js:604
runExample @ (index):37
(anonymous) @ (index):59

my index.html


<input id="input" type="text" />

<button id="sendBtn" disabled>Send</button>

<pre id="output"></pre>

<script src="./neffos.js"></script>
<script>
    var scheme = document.location.protocol == "https:" ? "wss" : "ws";
    var port = ":3811"
    var wsURL = "ws://localhost:3811/echo" 
    var outputTxt = document.getElementById("output");
    function addMessage(msg) {
        outputTxt.innerHTML += msg + "\n";
    }
    function handleError(reason) {
        console.log(reason);
        window.alert(reason);
    }
    function handleNamespaceConnectedConn(nsConn) {
        let inputTxt = document.getElementById("input");
        let sendBtn = document.getElementById("sendBtn");
        sendBtn.disabled = false;
        sendBtn.onclick = function () {
            const input = inputTxt.value;
            inputTxt.value = "";
            nsConn.emit("send", input);
            addMessage("Me: " + input);
        };
    }
    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) {
                        
                    },
                    chat: function (nsConn, msg) { // "chat" event.

                    }
                }
            },["123"]);
            // 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");
            // handleNamespaceConnectedConn(nsConn);
            conn.connect("default");
        } catch (err) {
            handleError(err);
        }
    }
    runExample();
  </script>

I used Query String to solve this problem.

change wsURL to ws://localhost:3811/echo?UserId=123

and remove ["123"] protocol in the dial method.

Can not we have a custom header on dial?

function dial(endpoint: string, connHandler: any, protocols?: string[]): Promise<Conn> {
    if (endpoint.indexOf("ws") == -1) {
        endpoint = "ws://" + endpoint;
    }

    return new Promise((resolve, reject) => {
        if (!WebSocket) {
            reject("WebSocket is not accessible through this browser.");
        }


        let namespaces = resolveNamespaces(connHandler, reject);
        if (isNull(namespaces)) {
            return;
        }

        let ws = new WebSocket(endpoint, protocols);
        let conn = new Conn(ws, namespaces);
        ws.binaryType = "arraybuffer";
        ws.onmessage = ((evt: MessageEvent) => {
            let err = conn.handle(evt);
            if (!isEmpty(err)) {
                reject(err);
                return;
            }

            if (conn.isAcknowledged()) {
                resolve(conn);
            }
        });
        ws.onopen = ((evt: Event) => {
            // let b = new Uint8Array(1)
            // b[0] = 1;
            // this.conn.send(b.buffer);
            ws.send(ackBinary);
        });
        ws.onerror = ((err: Event) => {
            conn.close();
            reject(err);
        });
    });
}

Like golang client

	client, err := neffos.Dial(
		// Optional context cancelation and deadline for dialing.
		nil,
		// The underline dialer, can be also a gobwas.Dialer/DefautlDialer or a gorilla.Dialer/DefaultDialer.
		// Here we wrap a custom gobwas dialer in order to send the username among, on the handshake state,
		// see `startServer().server.IDGenerator`.
		gobwas.Dialer(gobwas.Options{Header: gobwas.Header{"X-Username": []string{username}}}),
		// The endpoint, i.e ws://localhost:8080/path.
		endpoint,
		// The namespaces and events, can be optionally shared with the server's.
		serverAndClientEvents)

Contributor guide