Skip to content

Commit

Permalink
Add Socket.io example
Browse files Browse the repository at this point in the history
  • Loading branch information
alombarte committed Nov 12, 2024
1 parent d8afb58 commit 567ae3c
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 0 deletions.
13 changes: 13 additions & 0 deletions websockets/socket.io/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# **KrakenD Example with Socket.IO**

This repository provides an example of how to integrate KrakenD with Socket.IO.
Please see the documentation here: https://www.krakend.io/docs/enterprise/websockets/#integrating-krakend-with-socketio

> [Socket.IO](https://socket.io/) is a popular library to use bidirectional communication. Although Socket.IO name might sound as a WebSockets implementation, the reality is that Socket.IO operates on a **custom protocol** layered over WebSockets that is incompatible with plain WebSockets clients using the [WebSockets API](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications) (the one native in the JS standard lib). To connect to a Sockets.IO server you cannot use a WebSockets client, you must use a Sockets.IO client.
> KrakenD uses a pure WebSocket Protocol (RFC-6455) to connect to servers, but the Socket.IO protocol requires specific signaling to establish and maintain connections. By default, it attempts to **use the same endpoint for both HTTP and WebSocket communication**, and the connection details passed on a query string (e.g., `?EIO=4&transport=websocket`). This design can cause confusion when integrating with KrakenD, which manages HTTP and WebSocket traffic separately. Make sure to use `websockets` only when passing through KrakenD.
> Socket.IO also requires **dedicated connections for each client**. This approach is **incompatible with KrakenD's multiplexing system**, which optimizes resource usage by sharing WebSocket connections among multiple clients, so you are limited to use **direct WebSockets only**. Needles to say that handling individual client connections, leads to a much higher resource consumption.
> Integrating KrakenD with Socket.IO can open up powerful real-time communication features, but it comes with trade-offs. The need for dedicated per-client connections, the additional dependency footprint, and challenges in maintaining asynchronous logic and multi-threaded execution must be considered before committing to this setup.
59 changes: 59 additions & 0 deletions websockets/socket.io/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Socket.IO chat</title>
<style>
body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }

#form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
#input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
#input:focus { outline: none; }
#form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }

#messages { list-style-type: none; margin: 0; padding: 0; }
#messages > li { padding: 0.5rem 1rem; }
#messages > li:nth-child(odd) { background: #efefef; }
</style>
</head>
<body>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script>
let counter = 0;

const socket = io({
transports: ["websocket"],
auth: {
serverOffset: 0
},
ackTimeout: 10000,
retries: 3,
});

const form = document.getElementById('form');
const input = document.getElementById('input');
const messages = document.getElementById('messages');

form.addEventListener('submit', (e) => {
e.preventDefault();
if (input.value) {
const clientOffset = `${socket.id}-${counter++}`;
socket.emit('chat message', input.value, clientOffset);
input.value = '';
}
});

socket.on('chat message', (msg, serverOffset) => {
const item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
socket.auth.serverOffset = serverOffset;
});
</script>
</body>
</html>
48 changes: 48 additions & 0 deletions websockets/socket.io/krakend.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"version": 3,
"port": 8080,
"endpoints": [{
"endpoint": "/",
"output_encoding": "no-op",
"backend": [{
"url_pattern": "/",
"host": ["localhost:3000"],
"encoding": "no-op"
}]
}, {
"endpoint": "/socket.io/socket.io.js",
"output_encoding": "no-op",
"backend": [{
"url_pattern": "/socket.io/socket.io.js",
"host": ["localhost:3000"],
"encoding": "no-op"
}]
}, {
"endpoint": "/socket.io/",
"input_query_strings": ["*"],
"input_headers": ["*"],
"backend": [{
"url_pattern": "/socket.io/?EIO=4&transport=websocket",
"disable_host_sanitize": true,
"host": [
"ws://localhost:3000"
]
}],
"extra_config": {
"websocket": {
"read_buffer_size": 4096,
"write_buffer_size": 4096,
"message_buffer_size": 4096,
"max_message_size": 3200000,
"write_wait": "10s",
"pong_wait": "60s",
"ping_period": "54s",
"max_retries": 0,
"backoff_strategy": "exponential",
"enable_direct_communication": true,
"disable_otel_metrics": true
}
}

}]
}

0 comments on commit 567ae3c

Please sign in to comment.