lemunozm / message-io

Fast and easy-to-use event-driven network library.
Apache License 2.0
1.11k stars 74 forks source link

Support browser client connections (if not already?) #122

Closed lokimckay closed 2 years ago

lokimckay commented 2 years ago

Hello, I read through the docs but am still unsure if my use case is supported

I'm trying to connect to a message-io websocket server from a Chrome extension (i.e. the standard browser Websocket object)

Reproduction steps

  1. Setup a minimal example of message-io according to the readme example
  2. Remove TCP and UDP transports from the example
  3. Configure message-io to listen at 127.0.0.1:<port>
  4. Install this chrome extension (source here)
  5. Open the extension page
  6. Connect to 127.0.0.1:<port> in the URL field
  7. Note that "Client connected" is correctly reported by message-io in rust terminal
  8. Send a test message via the Request field

Expected outcome

image

Actual outcome

image

Why is no response being sent back?

lemunozm commented 2 years ago

Hi @lokimckay,

First of all, thanks for your great explanation and reproduction steps 😃

WebSocket can support two kinds of message data formats: binary and text. Since message-io handle the input/output data as binary, the WS adaptor used is only implemented for binary mode. The extension you're using sends data to the server in text mode, and message-io drops the message.

I tested allowing message-io to understand the Text message, but because the WS adaptor always sends in binary mode, the extension, in this case, is who drops the binary message.

I hope your real case can support binary messages. Adding the text format support to message-io could be possible, but there is some decision points as "how to send a WS message specifying the format in a generic send() of the message-io interface" that must be evaluated before.

lokimckay commented 2 years ago

Thanks for the great project and explanation @lemunozm 😄

Do you know if it is possible for the browser implementation of Websocket to send as binary data? (as you say is required?) I find it hard to determine this from their docs

I created a minimal reproduction repo using a simple index.html file and Javascript instead of the third-party chrome extension - but I still see the same behaviour that I reported in my issue

Can you tell me if I am still trying to send the messages as text?

https://github.com/lokimckay-references/message-io-122

lokimckay commented 2 years ago

Woops, answered my own question 🤦 I didn't understand that the javascript was literally sending a string to the Rust websocket, and it needed to instead send a byte array (like you said)

Fix: https://github.com/lokimckay-references/message-io-122/commit/10897f7a48ef7d44395dc32a42be375d2827354f Copy+paste of the diff:

 function onConnectButtonClick() {
+  ws.addEventListener("message", onMessageReceived);
 }

 function onSendMessageButtonClick() {
   console.log('Sending "Hello there!"');
-  ws.send("Hello there!");
+  ws.send(stringToByteArray("Hello there!"));
+}

+function stringToByteArray(str) {
+  const bytes = new Uint8Array(str.length);
+  for (let i = 0; i < str.length; i++) {
+    bytes[i] = str.charCodeAt(i);
+  }
+  return bytes;
+}

+async function onMessageReceived(event) {
+  const message = await event.data.text();
+  console.log("Received:", message);
+}

Behaves as expected 🎉

Will close the issue now, thanks for your help 😄

lemunozm commented 2 years ago

Thanks for responding with the solution 😃. Helpful for other users.

Anyway, I will try to improve message-io documentation to avoid this issue for the next person.

Regards