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)