Edit Page

Examples of the WebSocket API

🔧 Configuration

Sets localhost:8080 with admin:secret
Values are saved in your browser

The following requests create a collection with three change streams:

  • all bound at /messages/_streams/all

  • mine bound at /messages/_streams/mine

cURL

curl -i -X PUT '[INSTANCE-URL]/messages' \
  -H 'Authorization: Basic [BASIC-AUTH]' \
  -H 'Content-Type: application/json' \
  -d '{
    "streams" : [
      { "stages" : [
          {
              "_$match": {
                "_$or" : [ { "operationType": "insert" }, { "operationType": "update" } ]
            }
          }
      ],
        "uri" : "all"
      },
      { "stages" : [
          { "_$match" : { "fullDocument::name" : { "_$var" : "n" } } }
        ],
        "uri" : "mine"
      }
    ]
}'

HTTPie

echo '{
    "streams" : [
      { "stages" : [
          {
              "_$match": {
                "_$or" : [ { "operationType": "insert" }, { "operationType": "update" } ]
            }
          }
      ],
        "uri" : "all"
      },
      { "stages" : [
          { "_$match" : { "fullDocument::name" : { "_$var" : "n" } } }
        ],
        "uri" : "mine"
      }
    ]
}' | http PUT [INSTANCE-URL]/messages \
  'Authorization:Basic [BASIC-AUTH]' \
  'Content-Type:application/json'

JavaScript

fetch('[INSTANCE-URL]/messages', {
  method: 'PUT',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "streams" : [
      { "stages" : [
          {
              "_$match": {
                "_$or" : [ { "operationType": "insert" }, { "operationType": "update" } ]
            }
          }
      ],
        "uri" : "all"
      },
      { "stages" : [
          { "_$match" : { "fullDocument::name" : { "_$var" : "n" } } }
        ],
        "uri" : "mine"
      }
    ]
  })
})
.then(response => {
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Note
The request body is included in the examples above.

Note that the $match stage specifies a condition on the name property using fullDocument::name.

This is because the Change Event looks like:

{
    "fullDocument": {
        "_id": { "$oid": "5e15ff5779ca449eb20fdd09" },
        "message": "hi uji, how are you?",
        "name": "uji",
        "_etag": { "$oid": "5e15ff57a2e5700c3459e801" }
    },
    "documentKey": {
        "_id": { "$oid": "5e15ff5779ca449eb20fdd09" }
    },
    "updateDescription": null,
    "operationType": "insert"
}

Note the _links collection property showing the URIs of the change streams (returned with ?rep=SHAL).

cURL

curl -i -X GET '[INSTANCE-URL]/messages?rep=SHAL' \
  -H 'Authorization: Basic [BASIC-AUTH]'

HTTPie

http GET [INSTANCE-URL]/messages rep==SHAL \
  'Authorization:Basic [BASIC-AUTH]'

JavaScript

fetch('[INSTANCE-URL]/messages?rep=SHAL', {
  method: 'GET',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]'
  }
})
.then(response => {
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
{
    "_links": {
        "all": {
            "href": "/messages/_streams/all"
        },
        "mine": {
            "href": "/messages/_streams/mine"
        }
    }
}

Alternatively, you can define a single change stream that returns either all messages or only those sent by a specific name. This can be achieved using optional stages:

{
  "streams" : [
    { "stages" : [
          { "$ifvar": [ "n", { "_$match" : { "fullDocument::name" : { "_$var" : "n" } } } ] }
        ],
        "uri" : "withOptionalStage"
      }
    ]
}

To subscribe to the change streams, we’ll use websocat, a command-line client for WebSockets, like netcat (or curl) for ws://

Tip
You can install websocat following the instructions at https://github.com/vi/websocat#installation or downloading binaries from https://github.com/vi/websocat/releases

Connect to the change streams using the following command (assuming the default user admin exists with the default password):

$ websocat --text - autoreconnect:ws://admin:secret@127.0.0.1:8080/messages/_streams/all

To allow connections without authentication, you can define the following permission

cURL

curl -i -X POST '[INSTANCE-URL]/acl' \
  -H 'Authorization: Basic [BASIC-AUTH]' \
  -H 'Content-Type: application/json' \
  -d '{
    "_id": "unauthenticatedCanConnectToMyWebSocket",
    "predicate": "path-prefix('"'"'/messages/_streams/all'"'"')",
    "priority": 0,
    "roles": [ "$unauthenticated" ]
}'

HTTPie

echo '{
    "_id": "unauthenticatedCanConnectToMyWebSocket",
    "predicate": "path-prefix('"'"'/messages/_streams/all'"'"')",
    "priority": 0,
    "roles": [ "$unauthenticated" ]
}' | http POST [INSTANCE-URL]/acl \
  'Authorization:Basic [BASIC-AUTH]' \
  'Content-Type:application/json'

JavaScript

fetch('[INSTANCE-URL]/acl', {
  method: 'POST',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "_id": "unauthenticatedCanConnectToMyWebSocket",
    "predicate": "path-prefix('/messages/_streams/all')",
    "priority": 0,
    "roles": [ "$unauthenticated" ]
  })
})
.then(response => {
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

With this permission in place, you can connect to the WebSocket without authentication:

$ websocat --text - autoreconnect:ws://127.0.0.1:8080/messages/_streams/all

If you now create a new document in the collection messages

cURL

curl -i -X POST '[INSTANCE-URL]/messages' \
  -H 'Authorization: Basic [BASIC-AUTH]' \
  -H 'Content-Type: application/json' \
  -d '{
    "message": "Hello WebSockets!",
    "name": "uji"
}'

HTTPie

echo '{
    "message": "Hello WebSockets!",
    "name": "uji"
}' | http POST [INSTANCE-URL]/messages \
  'Authorization:Basic [BASIC-AUTH]' \
  'Content-Type:application/json'

JavaScript

fetch('[INSTANCE-URL]/messages', {
  method: 'POST',
  headers: {
    'Authorization': 'Basic [BASIC-AUTH]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "message": "Hello WebSockets!",
    "name": "uji"
  })
})
.then(response => {
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

You get the following output from websocat:

$ websocat --text - autoreconnect:ws://admin:secret@127.0.0.1:8080/messages/_streams/all
{"fullDocument":{"_id":{"$oid":"62166d53ebdcd56455a1a7ab"},"message":"Hello WebSockets!","name":"uji","_etag":{"$oid":"62166d53ebdcd56455a1a7aa"}},"documentKey":{"_id":{"$oid":"62166d53ebdcd56455a1a7ab"}},"operationType":"insert"}