Getting Started With WebSockets
You can connect to a CaseFusion project using a WebSocket interface and get updates on data held in a collection in real-time.
This guide will show you how to get started with CaseFusion' WebSockets interface and JavaScript. WebSockets are language-agnostic, so you can apply the same set of steps in your stack of choice.
Before You Begin
You will need a CaseFusion project. If you don’t already have one, the easiest way to get started is with our managed cloud hosting. You can also self-host CaseFusion, ensuring the WEBSOCKETS_ENABLED environment variable is set to true.
Create a new collection called messages, with a date_created field enabled in the Optional System Fields pane on collection creation. Create a text field called text and a second called user.
If it doesn’t already exist, create a user with a role that can execute read and create operations on the collection.
Finally in the CaseFusion Data Studio, create a static access token for the user, copy it, and save the user profile.
Create an index.html file and open it in your code editor. Add the following boilerplate code:
<!DOCTYPE html>
<html>
<body>
<script>
const url = 'wss://your-directus-url/websocket';
const access_token = 'your-access-token';
const collection = 'messages';
</script>
</body>
</html><!DOCTYPE html>
<html>
<body>
<script>
const url = 'wss://your-directus-url/websocket';
const access_token = 'your-access-token';
const collection = 'messages';
</script>
</body>
</html>Make sure to replace your-directus-url and your-access-token with your project and user details.
Create a Connection
At the bottom of your <script>, add the following code to establish a new WebSocket connection:
const connection = new WebSocket(url);const connection = new WebSocket(url);To add some feedback, add the following event handlers below your connection variable:
connection.addEventListener('open', function () {
console.log({ event: 'onopen' });
});
connection.addEventListener('message', function (message) {
const { data } = JSON.parse(message);
console.log({ event: 'onmessage', data });
});
connection.addEventListener('close', function () {
console.log({ event: 'onclose' });
});
connection.addEventListener('error', function (error) {
console.log({ event: 'onerror', error });
});connection.addEventListener('open', function () {
console.log({ event: 'onopen' });
});
connection.addEventListener('message', function (message) {
const { data } = JSON.parse(message);
console.log({ event: 'onmessage', data });
});
connection.addEventListener('close', function () {
console.log({ event: 'onclose' });
});
connection.addEventListener('error', function (error) {
console.log({ event: 'onerror', error });
});Open index.html in your browser and open the Developer Tools. You should see the onopen event logged in the console.
Authenticate Your Connection
Once a connection is opened, you have to send a message to authenticate your session. If you don't, you'll receive a message indicating there was an authentication failure.
connection.addEventListener('open', function () {
console.log({ event: 'onopen' });
connection.send(
JSON.stringify({
type: 'auth',
access_token,
})
);
});connection.addEventListener('open', function () {
console.log({ event: 'onopen' });
connection.send(
JSON.stringify({
type: 'auth',
access_token,
})
);
});You should immediately receive a message in return to confirm. The connection is now authenticated and will remain open, ready to send and receive data.
Learn more about WebSocket authentication here.
Create a Subscription
After subscribing to collections over your connection, you will receive new messages whenever items in the collection are created, updated, or deleted.
At the bottom of your <script>, create a new function which subscribes to a collection:
function subscribe() {
connection.send(
JSON.stringify({
type: 'subscribe',
collection: 'messages',
query: { fields: ['*'] },
})
);
}function subscribe() {
connection.send(
JSON.stringify({
type: 'subscribe',
collection: 'messages',
query: { fields: ['*'] },
})
);
}Save your file, refresh your browser, and open your browser console. Run this function by typing:
subscribe();subscribe();You will receive a message in response to confirm the subscription has been initialized. Then, new messages will be sent when there’s an update on the collection.
Create Item
Create a new function that sends a message over the connection with a create action:
function createItem(text, user) {
connection.send(
JSON.stringify({
type: 'items',
collection: 'messages',
action: 'create',
data: { text, user },
})
);
}function createItem(text, user) {
connection.send(
JSON.stringify({
type: 'items',
collection: 'messages',
action: 'create',
data: { text, user },
})
);
}Save your file, refresh your browser, and open your browser console. Create a few new items by using your new function directly in the console:
createItem('Hello World!', 'Ben');
createItem('Hello Universe!', 'Rijk');
createItem('Hello Everyone Everywhere All At Once!', 'Kevin');createItem('Hello World!', 'Ben');
createItem('Hello Universe!', 'Rijk');
createItem('Hello Everyone Everywhere All At Once!', 'Kevin');Every time you create an item, you will receive a message in response with the new item as created in your CaseFusion collection.
Get Latest Item
You can use your connection to perform all CRUD actions by using type: 'items' in the payload and including the respective action. Create a new function for reading the latest message:
function readLatestItem() {
connection.send(
JSON.stringify({
type: 'items',
collection: 'messages',
action: 'read',
query: { limit: 1, sort: '-date_created' },
})
);
}function readLatestItem() {
connection.send(
JSON.stringify({
type: 'items',
collection: 'messages',
action: 'read',
query: { limit: 1, sort: '-date_created' },
})
);
}Send the message over the connection by entering readLatestItem() your browser console. You will receive a message with the result of your query on the collection.
Pings To Keep Connection Active
You may have noticed that, periodically, you will receive a message with a type of ping. This serves two purposes:
- To act as a periodic message to stop your connection from closing due to inactivity. This may be required by your application technology stack.
- To verify that the connection is still active.
On Directus Cloud, this feature is enabled. If you are self-hosting, you can alter this behavior with the WEBSOCKETS_HEARTBEAT_ENABLED and WEBSOCKETS_HEARTBEAT_PERIOD environment variables.
You may wish to exclude these messages from your application logic.
In Summary
In this guide, you have successfully created a new WebSocket connection, authenticated yourself, and performed CRUD operations over the connection. You have also created your first subscription.
Learn more about subscriptions with WebSockets with CaseFusion.
Full Code Sample
<!DOCTYPE html>
<html>
<body>
<script>
const url = 'wss://your-directus-url/websocket';
const access_token = 'your-access-token';
const collection = 'messages';
const connection = new WebSocket(url);
connection.addEventListener('open', function () {
console.log({ event: 'onopen' });
connection.send(
JSON.stringify({
type: 'auth',
access_token,
})
);
});
connection.addEventListener('message', function (message) {
const data = JSON.parse(message.data);
console.log({ event: 'onmessage', data });
});
connection.addEventListener('close', function () {
console.log({ event: 'onclose' });
});
connection.addEventListener('error', function (error) {
console.log({ event: 'onerror', error });
});
function subscribe() {
connection.send(
JSON.stringify({
type: 'subscribe',
collection: 'messages',
query: {
fields: ['*'],
},
})
);
}
function createItem(text, user) {
connection.send(
JSON.stringify({
type: 'items',
collection: 'messages',
action: 'create',
data: { text, user },
})
);
}
function readLatestItem() {
connection.send(
JSON.stringify({
type: 'items',
collection: 'messages',
action: 'read',
query: { limit: 1, sort: '-date_created' },
})
);
}
</script>
</body>
</html><!DOCTYPE html>
<html>
<body>
<script>
const url = 'wss://your-directus-url/websocket';
const access_token = 'your-access-token';
const collection = 'messages';
const connection = new WebSocket(url);
connection.addEventListener('open', function () {
console.log({ event: 'onopen' });
connection.send(
JSON.stringify({
type: 'auth',
access_token,
})
);
});
connection.addEventListener('message', function (message) {
const data = JSON.parse(message.data);
console.log({ event: 'onmessage', data });
});
connection.addEventListener('close', function () {
console.log({ event: 'onclose' });
});
connection.addEventListener('error', function (error) {
console.log({ event: 'onerror', error });
});
function subscribe() {
connection.send(
JSON.stringify({
type: 'subscribe',
collection: 'messages',
query: {
fields: ['*'],
},
})
);
}
function createItem(text, user) {
connection.send(
JSON.stringify({
type: 'items',
collection: 'messages',
action: 'create',
data: { text, user },
})
);
}
function readLatestItem() {
connection.send(
JSON.stringify({
type: 'items',
collection: 'messages',
action: 'read',
query: { limit: 1, sort: '-date_created' },
})
);
}
</script>
</body>
</html>