{"id":15019707,"url":"https://github.com/yaroslaff/ws-emit","last_synced_at":"2025-10-24T14:32:23.367Z","repository":{"id":62589606,"uuid":"422340173","full_name":"yaroslaff/ws-emit","owner":"yaroslaff","description":"Easily emit websocket events from any sources (python, php, bash, whatever) using redis or HTTP interface","archived":false,"fork":false,"pushed_at":"2022-05-04T11:00:48.000Z","size":57,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-31T02:36:23.081Z","etag":null,"topics":["cli","curl","easy","easy-to-use","emitting","flask","http","microservice","php","python","redis","shell","webserver","websocket","websockets"],"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/yaroslaff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-28T20:02:59.000Z","updated_at":"2024-07-10T22:55:35.000Z","dependencies_parsed_at":"2022-11-03T17:56:37.775Z","dependency_job_id":null,"html_url":"https://github.com/yaroslaff/ws-emit","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaroslaff%2Fws-emit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaroslaff%2Fws-emit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaroslaff%2Fws-emit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaroslaff%2Fws-emit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yaroslaff","download_url":"https://codeload.github.com/yaroslaff/ws-emit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237990671,"owners_count":19398475,"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":["cli","curl","easy","easy-to-use","emitting","flask","http","microservice","php","python","redis","shell","webserver","websocket","websockets"],"created_at":"2024-09-24T19:53:55.037Z","updated_at":"2025-10-24T14:32:18.679Z","avatar_url":"https://github.com/yaroslaff.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WS-Emit\n\nWS-Emit is simple microservice app to send instant messages (websocket events) from backend to frontend web applications running in browser (one way). ws-emit handles CORS configuration and authentication mechanism for different *room-spaces*.\n\nExample usages:\n- ecommerce website may update prices, stock and orders information on page in realtime, without need to refresh. \n- social network may show user if someone is writing new comment right now and display comment when it will be submitted\n- backend may update frontend about status of long-running requests, such as 'build is N% ready', 'deploying'\n\nWS-Emit benefits:\n- Isolated microservice, not requires any integration with your application\n- Compatible with application in any programming languages (if they can send HTTP requests or publish data to redis), any frameworks, any application web server \n\nWS-Emit is based on [Flask-SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) and sending message is as simple as in any other flask-socketio application:\n\n~~~python3\nsocketio.emit('update', data, room='time')\n~~~\n\nor via HTTP interface (see below):\n~~~\ncurl -d @x.json -H \"Content-Type: application/json\" -X POST http://localhost:8899/emit\n~~~\n\n## Screencast\nSee below for detailed explanation what every example does.\n\n[![ws-emit screencast](https://img.youtube.com/vi/yQCIBFuogg4/0.jpg)](https://www.youtube.com/watch?v=yQCIBFuogg4)\n\n## Installation\n~~~\npip3 install ws-emit\n~~~\nor, install right from github repo:\n~~~\npip3 install git+https://github.com/yaroslaff/ws-emit\n~~~\n\nIf you want to install as systemd service:\n~~~\ncp /usr/local/ws-emit/contrib/ws-emit /etc/default/\ncp /usr/local/ws-emit/contrib/ws-emit.service /etc/systemd/system/\nsystemctl daemon-reload\nsystemctl enable ws-emit\nsystemctl start ws-emit\n~~~\nIf you want to adjust CORS, ADDRESS or SECRET settings, edit /etc/default/ws-emit and restart service.\n\nIf you want to run manually from shell:\n~~~\n# specify default parameters\nws-emit.py -a 0.0.0.0:8899 --cors http://localhost:7788 --secret 123\n~~~\n\n## Authentication and room-spaces\nRoom name optionally may have format roomspace::roomname (separated by '::'). When client wants to join such room it must provide secret matching redis key `ws-emit::secret::*roomspace*`. If secrets aren't match, join request is ignored. All rooms in same roomspace shares same secret.  Backend must set this key in redis (e.g. `SET ws-emit::secret::myroom MySecret_123`) and pass secret to frontend.\n\nRooms without '::' in name, are public, anyone can join it. They are not suited to send any sensitive info.\n\n## Emitting messages over HTTP(s)\nIt's possible to emit messages from any sources (any programming languages, even from PHP or Perl or shell scripts. really.) using HTTP interface. Here is simple example how to emit websocket events right from shell using curl.\n\nHTTP emitting requres secret, like:\n~~~\n./ws-emit.py --secret MySecret\n~~~\n\nor set `SECRET=MySecret` in /etc/default/ws-emit and restart ws-emit service.\n\nJSON file `x.json`:\n~~~\n{\n\t\"event\": \"update\",\n\t\"room\": \"time\",\n\t\"data\": {\n\t\t\"time\": 111111\n\t},\n\t\"namespace\": null,\n\t\"secret\": \"123\"\n}\n~~~\n\ncommand:\n~~~\ncurl -d @x.json -H \"Content-Type: application/json\" -X POST http://localhost:8899/emit\n~~~\n\nYou may run `time.py` example (see below) and execute this curl statement, it will send time 111111 and it will be displayed in browser for short time (less then 1s) until overwritten by next update.\n\n\n## ws-emit over nginx as https (wss://) proxy\nrun ws-emit at other port, edit `/etc/default/ws-emit`:\n~~~\n...\nADDRESS=\"127.0.0.1:8898\"\n...\n~~~\n\n`/etc/nginx/sites-available/ws-emit`:\n~~~\nmap $http_upgrade $connection_upgrade {\n    default Upgrade;\n    ''      close;\n}\n\nserver {\n\tlisten 8899 ssl;\n\tserver_name ...;\n\tssl_certificate ...;\n\tssl_certificate_key ...;\n\t\n\tlocation / {\n\t\tproxy_pass http://127.0.0.1:8898;\n\t\tproxy_http_version 1.1;\n\t\tproxy_set_header Upgrade $http_upgrade;\n\t\tproxy_set_header Connection $connection_upgrade;\n\t\tproxy_set_header Host $host;\n   \t}\t\n}\n~~~\n\n## Examples\n\n### time\nTime is simplest example. No authentication at all.\n\nStart `/usr/local/ws-emit/example/time.py` in console. Navigate browser to http://localhost:7788/. You will see current system unixtime, it will update every second. \n\nMake sure addresses are exactly matching to CORS value in ws-emit (--cors option or CORS= parameter in /etc/default/ws-emit), http://localhost:7788 (default) and http://127.0.0.1:7788 are different\n\n### dir2web\nDir2web is more complex example with authentication and room-spaces.\n\nCreate test web directory, e.g. `mkdir /tmp/ws-emit`.\nStart `/usr/local/ws-emit/example/dir2web.py /tmp/ws-emit` in console and open http://localhost:7788 in browser. You will see all files in this directory, if you will create new file (`echo aaa \u003e /tmp/ws-emit/aaa.txt`), it will be immediately listed in browser. You can open file in browser, and if you will change file content  (`echo aaa2 \u003e /tmp/ws-emit/aaa.txt`) it will be immediately updated in browser.\n\ndir2web uses roomspace `dir` and sets access key to this roomspace as redis-key `ws-emit::room_secret::dir`. This key is provided to JS code running in browser, and then JS code send key when join rooms inside this roomspace.\n\n### subspy\nSubspy `/usr/local/ws-emit/example/subspy.py` it simple utility to *sniff* traffic in publish/subscribe redis channel.\n\nExample output (from time.py example):\n~~~\n# /usr/local/ws-emit/example/subspy.py \nAll channels: [b'flask-socketio']\nINT: 1\n{'method': 'emit', 'event': 'update', 'data': {'time': 1639178370}, 'namespace': '/', 'room': 'time', 'skip_sid': None, 'callback': None, 'host_id': 'ce56fbc176624c7e8511a583cd5030a8'}\n{'method': 'emit', 'event': 'update', 'data': {'time': 1639178371}, 'namespace': '/', 'room': 'time', 'skip_sid': None, 'callback': None, 'host_id': 'ce56fbc176624c7e8511a583cd5030a8'}\n~~~\n\nYou may use subspy to generate websocket events in other languages (But messages must be serialized in python [pickle](https://docs.python.org/3/library/pickle.html) format).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaroslaff%2Fws-emit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyaroslaff%2Fws-emit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaroslaff%2Fws-emit/lists"}