{"id":20525968,"url":"https://github.com/codeyellowbv/high-templar","last_synced_at":"2025-04-14T04:08:35.960Z","repository":{"id":44612108,"uuid":"99562788","full_name":"CodeYellowBV/high-templar","owner":"CodeYellowBV","description":"A python framework for creating a server which handles websockets for an existing API","archived":false,"fork":false,"pushed_at":"2024-12-18T19:30:40.000Z","size":359,"stargazers_count":5,"open_issues_count":7,"forks_count":4,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-14T04:08:31.293Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CodeYellowBV.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-07T09:47:09.000Z","updated_at":"2024-04-11T20:55:57.000Z","dependencies_parsed_at":"2024-12-09T13:34:21.514Z","dependency_job_id":"4015ee62-cd27-4e89-ad66-4f4784ad1b57","html_url":"https://github.com/CodeYellowBV/high-templar","commit_stats":{"total_commits":108,"total_committers":11,"mean_commits":9.818181818181818,"dds":0.4537037037037037,"last_synced_commit":"aef087d66cfacd2d7bd072f6018cbcb74d983067"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodeYellowBV%2Fhigh-templar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodeYellowBV%2Fhigh-templar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodeYellowBV%2Fhigh-templar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodeYellowBV%2Fhigh-templar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CodeYellowBV","download_url":"https://codeload.github.com/CodeYellowBV/high-templar/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248819404,"owners_count":21166477,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T23:11:35.411Z","updated_at":"2025-04-14T04:08:35.942Z","avatar_url":"https://github.com/CodeYellowBV.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"====================\nhigh-templar\n====================\n\n|build_status|_ |code_coverage|_\n\nA python framework for creating a stateful server which handles websocket functionality for an existing HTTP only API.\n\nFlow\n=======\n\n\n- A client opens a websocket connection with a High-templar instance.\n- The HT instance proxies the request to the API, which in turn handles authentication and provides a list of rooms.\n- The HT instance tells the client what rooms he is allowed to subscribe to.\n- The client subscribes to one or more rooms\n- When receiving a trigger from the API, the HT instance publishes the received data to the specified rooms.\n\n\n\nInstallation\n==============\n\n\n\n.. code:: bash\n\n    pip install -Ur requirements.txt\n    pip install high-templar\n\n    # Install rabbitmq and create a user.\n    apt install rabbitmq-server\n    rabbitmqctl add_user rabbitmq rabbitmq\n    rabbitmqctl set_user_tags rabbitmq administrator\n    rabbitmqctl set_permissions -p / rabbitmq \".*\" \".*\" \".*\"\n\n    # Take a look at `install` folder for examples for systemd.\n\n\nMotivation\n==============\n\n\nThis project is created for handling websockets for a django instance.\nDjango doesn't support websockets out of the box. To add websocket support to Django, one can either\nmonkey patch the Django WSGI with gevent, or use django-channels which requires a lot of configuration and needs you to manage its workers.\n\nHigh-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.\n\nArchitecture\n==============\n\n\n|architecture|_\n\nThe Rabbitmq rewrite made it possible\n\n\n2 concepts are fundamental:\n\n1. Connection: a single websocket bi-directional data pipe connection.\n2. Room: an authenticated place where data is send from the server.\n\n\nNormally 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.\n\n\n\n\n\nInterfaces\n==============\n\n\nStarting a connection\n------------------------\n\nStarting up a connection\n\nWhen creating a connection, and authentication can be done:\n\nResponse:\n\n.. code:: json\n\n    {\n        \"is_authenticated\": True,\n        \"allowed_rooms\": [{\n            \"target\": \"message\",\n            \"customer\": \"1\"\n        }]\n    }\n\nWhen creating a connection, and authentication can not be done:\n\nResponse:\n\n.. code:: json\n\n    {\n        \"is_authenticated\": False\n    }\n\n\nSubscribing to a room\n------------------------\n\nRequest:\n\n.. code:: json\n\n    {\n        \"type\": \"subscribe\",\n        \"room\": {\n            \"target\": \"message\",\n            \"customer\": \"1\"\n        },\n        \"requestId\": \"1\"\n    }\n\nResponse when you have permission:\n\n.. code:: json\n\n    { \"code\": \"success\" }\n\n\nResponse when you don't have permission or the room doesn't exist:\n\n.. code:: json\n\n    {\n        \"code\": \"error\",\n        \"message\": \"room-not-found\"\n    }\n\n\nTODO: document unsubscribe\n\n\nRoom permissions\n------------------------\n\nThe 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:\n\n\n.. code:: json\n\n    {\n        \"is_authenticated\": True,\n        \"allowed_rooms\": [{\n            \"room\": \"user-login\",\n            \"department\": \"finance\"\n        }, {\n            \"room\": \"user-logout\",\n            \"department\": \"finance\"\n        }, {\n            \"target\": \"chat-create\",\n            \"customer\": \"*\"\n        }, {\n            \"target\": \"chat-update\",\n            \"customer\": \"*\"\n        }]\n    }\n\n\nThe 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:\n\n.. code:: json\n\n    {\n        \"type\": \"subscribe\",\n        \"room\": {\n            \"target\": \"chat-create\",\n            \"customer\": \"*\"\n        },\n        \"requestId\": \"1\"\n    }\n\n.. code:: json\n\n    {\n        \"type\": \"subscribe\",\n        \"room\": {\n            \"target\": \"chat-create\",\n            \"customer\": \"1\"\n        },\n        \"requestId\": \"2\"\n    }\n\n.. code:: json\n\n    {\n        \"type\": \"subscribe\",\n        \"room\": {\n            \"target\": \"chat-create\",\n            \"customer\": \"2\"\n        },\n        \"requestId\": \"3\"\n    }\n\n\nSending data to a room\n------------------------\n\n\nTo send data to a room, send a POST request to the server:\n\n.. code:: json\n\n    {\n        [\n            {\n                \"target\": \"chat-create\",\n                \"customer\": \"*\"\n            },\n            {\n                \"target\": \"chat-create\",\n                \"customer\": \"1\"\n            },\n            {\n                \"target\": \"chat-create\",\n                \"customer\": \"2\"\n            }\n        ],\n        \"data\": \"Example text body\"\n    }\n\n\nUsing the `*`, we can cut 2 rooms. So this is the exactly the same as:\n\n.. code:: json\n\n    {\n        [\n            {\n                \"target\": \"chat-create\",\n                \"customer\": \"*\"\n            }\n        ],\n        \"data\": \"Example text body\"\n    }\n\nTODO: Implement this\nTODO: Add test for trigger http endpoint\n\n\n\nPing pong\n------------------------\n\nThe frontend can send a ping message to check if the websocket connection is still working.\nHT will send a pong message if the connection is still open\n\nRequest:\n\n.. code:: text\n\n    ping\n\nResponse:\n\n.. code:: text\n\n    pong\n\nTests\n=======\n\nRun high templar first:\n`./run`\n\nAfter it is started, you can run all tests:\n`./test`\n\nOr run a specific test:\n`./test -v tests/tests/test_unsubscribe.py::TestUnSubscribe::test_unsubscribe_to_room`\n\nOrigin\n=======\n\nThis 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.\n\n\n.. |architecture| image:: architecture.png\n.. _archon: https://github.com/JasperStam/archon\n.. |build_status| image:: https://travis-ci.org/CodeYellowBV/high-templar.svg?branch=master\n.. _build_status: https://travis-ci.org/CodeYellowBV/high-templar\n.. |code_coverage| image:: https://codecov.io/gh/CodeYellowBV/high-templar/branch/master/graph/badge.svg\n.. _code_coverage: https://codecov.io/gh/CodeYellowBV/high-templar\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeyellowbv%2Fhigh-templar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodeyellowbv%2Fhigh-templar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeyellowbv%2Fhigh-templar/lists"}