Skip to main content

high-templar

build_status code_coverage

A python framework for creating a stateful server which handles websocket functionality for an existing HTTP only API.

Flow

  • A client opens a websocket connection with a High-templar instance.

  • The HT instance proxies the request to the API, which in turn handles authentication and provides a list of rooms.

  • The HT instance tells the client what rooms he is allowed to subscribe to.

  • The client subscribes to one or more rooms

  • When receiving a trigger from the API, the HT instance publishes the received data to the specified rooms.

Installation

pip install -Ur requirements.txt
pip install high-templar

# Install rabbitmq and create a user.
apt install rabbitmq-server
rabbitmqctl add_user rabbitmq rabbitmq
rabbitmqctl set_user_tags rabbitmq administrator
rabbitmqctl set_permissions -p / rabbitmq ".*" ".*" ".*"

# Take a look at `install` folder for examples for systemd.

Motivation

This project is created for handling websockets for a django instance. Django doesn’t support websockets out of the box. To add websocket support to Django, one can either monkey patch the Django WSGI with gevent, or use django-channels which requires a lot of configuration and needs you to manage its workers.

High-templar uses a similar approach to django-channels, but uses internal HTTP requests to communicate with the existing Django instance. High-templar keeps track of the active websocket connections, which allows the Django instance to remain stateless.

Architecture

architecture

The Rabbitmq rewrite made it possible

2 concepts are fundamental:

  1. Connection: a single websocket bi-directional data pipe connection.

  2. Room: an authenticated place where data is send from the server.

Normally only 1 connection is created during the entire session, but many, many rooms are subscribed to using this single connection. When a connection is created, the server responds with the allowed rooms for that user. A room is identified by a hash, and upon subscribing the client needs to specify a unique requestId that identifies the subscription to that room. That requestId can be used to match messages send from the server to a specific room. It is also used to unsubscribe from a room.

Interfaces

Starting a connection

Starting up a connection

When creating a connection, and authentication can be done:

Response:

{
    "is_authenticated": True,
    "allowed_rooms": [{
        "target": "message",
        "customer": "1"
    }]
}

When creating a connection, and authentication can not be done:

Response:

{
    "is_authenticated": False
}

Subscribing to a room

Request:

{
    "type": "subscribe",
    "room": {
        "target": "message",
        "customer": "1"
    },
    "requestId": "1"
}

Response when you have permission:

{ "code": "success" }

Response when you don’t have permission or the room doesn’t exist:

{
    "code": "error",
    "message": "room-not-found"
}

TODO: document unsubscribe

Room permissions

The initial message send from the server contains an allowed_rooms key. This allowed_rooms key determines which rooms which the client can subscribe to. Upon subscribing, the server checks if the client is allowed into the room, but once connected no futher permission checking is done. An example server response upon creating a connection:

{
    "is_authenticated": True,
    "allowed_rooms": [{
        "room": "user-login",
        "department": "finance"
    }, {
        "room": "user-logout",
        "department": "finance"
    }, {
        "target": "chat-create",
        "customer": "*"
    }, {
        "target": "chat-update",
        "customer": "*"
    }]
}

The key / value pairs have no meaning, other then identifying a room. An exception is the special * character, which means that anything will match in place of that character. For the response above, it means the client can connect to the 4 rooms described in allowed_rooms, but also to:

{
    "type": "subscribe",
    "room": {
        "target": "chat-create",
        "customer": "*"
    },
    "requestId": "1"
}
{
    "type": "subscribe",
    "room": {
        "target": "chat-create",
        "customer": "1"
    },
    "requestId": "2"
}
{
    "type": "subscribe",
    "room": {
        "target": "chat-create",
        "customer": "2"
    },
    "requestId": "3"
}

Sending data to a room

To send data to a room, send a POST request to the server:

{
    [
        {
            "target": "chat-create",
            "customer": "*"
        },
        {
            "target": "chat-create",
            "customer": "1"
        },
        {
            "target": "chat-create",
            "customer": "2"
        }
    ],
    "data": "Example text body"
}

Using the *, we can cut 2 rooms. So this is the exactly the same as:

{
    [
        {
            "target": "chat-create",
            "customer": "*"
        }
    ],
    "data": "Example text body"
}

TODO: Implement this TODO: Add test for trigger http endpoint

Ping pong

The frontend can send a ping message to check if the websocket connection is still working. HT will send a pong message if the connection is still open

Request:

ping

Response:

pong

Tests

Run high templar first: ./run

After it is started, you can run all tests: ./test

Or run a specific test: ./test -v tests/tests/test_unsubscribe.py::TestUnSubscribe::test_unsubscribe_to_room

Origin

This repository is based on archon. Archon is a framework for creating full fledged websocket based CRUD APIs. High-templar is only half the framework of Archon, as it relies on an existing API and only provides pubsub.

Metadata

Release files for high-templar 3.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for high-templar 3.1.0
File Size Uploaded Provenance Actions
high_templar-3.1.0.tar.gz 16.5 kB Without provenance Details for high_templar-3.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for high-templar 3.1.0
File Interpreter ABI Platform Actions
high_templar-3.1.0-py3-none-any.whl Python 3 none any Details for high_templar-3.1.0-py3-none-any.whl

Total release size: 34.7 kB

Release files / high_templar-3.1.0.tar.gz

Download URL high_templar-3.1.0.tar.gz
Size 16.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a5329ab345b576b504b784cb9f01d9fd9dabef526348d862940f0c2005f9d1ea
BLAKE2b-256 checksum
How to use checksums
63f5afada82ee8be1a7061fa50beef24c8174151b43365fe49c697842cb08746
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release files / high_templar-3.1.0-py3-none-any.whl

Download URL high_templar-3.1.0-py3-none-any.whl
Size 18.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7352c3e8da1037f35d83315e0ecf8818895993778386c0d8d01f88a0f22bcbad
BLAKE2b-256 checksum
How to use checksums
9448c0227428cc7a22e73b5bfdbee68a7dfcd9748aa7198cca504f589ac905e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Security for high-templar 3.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page