{"id":27283862,"url":"https://github.com/purplesyringa/gevent-ws","last_synced_at":"2025-04-11T18:46:21.843Z","repository":{"id":57434109,"uuid":"242759584","full_name":"purplesyringa/gevent-ws","owner":"purplesyringa","description":"A free MIT-licensed websocket library for gevent","archived":false,"fork":false,"pushed_at":"2020-05-11T17:32:16.000Z","size":24,"stargazers_count":3,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T19:04:19.548Z","etag":null,"topics":["gevent","server","websocket","websocket-server"],"latest_commit_sha":null,"homepage":null,"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/purplesyringa.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":"2020-02-24T14:37:25.000Z","updated_at":"2024-01-31T22:58:13.000Z","dependencies_parsed_at":"2022-08-27T22:31:57.267Z","dependency_job_id":null,"html_url":"https://github.com/purplesyringa/gevent-ws","commit_stats":null,"previous_names":["purplesyringa/gevent-ws","imachug/gevent-ws"],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purplesyringa%2Fgevent-ws","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purplesyringa%2Fgevent-ws/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purplesyringa%2Fgevent-ws/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purplesyringa%2Fgevent-ws/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/purplesyringa","download_url":"https://codeload.github.com/purplesyringa/gevent-ws/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248462002,"owners_count":21107775,"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":["gevent","server","websocket","websocket-server"],"created_at":"2025-04-11T18:46:21.141Z","updated_at":"2025-04-11T18:46:21.824Z","avatar_url":"https://github.com/purplesyringa.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gevent-ws\n\nA fast, MIT-licensed alternative to the abandoned non-free (as in freedom) [gevent-websocket](https://gitlab.com/noppo/gevent-websocket).\n\n\n## Why?\n\nIt's MIT-licensed, so it can be included to almost all software (both open-source and closed-source) without any licensing issues, as opposed to *gevent-websocket*. And it's several times faster!\n\n\n## Installation\n\n*gevent-ws* can be installed from PyPI and GitHub.\n\n\n### PyPI\n\n```shell\n$ pip3 install gevent-ws\n```\n\n\n### GitHub\n\n```shell\n$ git clone https://github.com/imachug/gevent-ws.git\n$ cd gevent-ws\n$ python3 setup.py install\n```\n\n\n## Example\n\n### A simple echo server\n\n```python3\nfrom gevent.pywsgi import WSGIServer\nfrom gevent_ws import WebSocketHandler\n\n\ndef app(env, start_response):\n    ws = env[\"wsgi.websocket\"]\n    while True:\n        msg = ws.receive()\n        if msg is None:\n            break\n        ws.send(msg)\n    return [b\"Bye\"]\n\n\nserver = WSGIServer((\"\", 8080), app, handler_class=WebSocketHandler)\nserver.serve_forever()\n```\n\n\n### Both HTTP and websocket on a single port\n\n```python3\nfrom gevent.pywsgi import WSGIServer\nfrom gevent_ws import WebSocketHandler\n\n\ndef app(env, start_response):\n    if \"wsgi.websocket\" in env:\n        ws = env[\"wsgi.websocket\"]\n        while True:\n            msg = ws.receive()\n            if msg is None:\n                break\n            ws.send(msg)\n        return [b\"Bye\"]\n    else:\n        start_response(\"200 OK\", [\n            (\"Content-Type\", \"text/html, charset=utf-8\")\n        ])\n\n        return [\n            b\"\"\"\n                \u003cscript\u003e\n                    const ws = new WebSocket(\"ws://127.0.0.1:8080/\");\n                    ws.onopen = () =\u003e {\n                        ws.send(\"Hello, world!\");\n                    };\n                    ws.onmessage = e =\u003e {\n                        ws.send(e.data);\n                    };\n                \u003c/script\u003e\n            \"\"\"\n        ]\n\n\nserver = WSGIServer((\"\", 8080), app, handler_class=WebSocketHandler)\nserver.serve_forever()\n```\n\n\n## Docs\n\n### `gevent_ws.WebSocketHandler`\n\nThe main class. Pass it to `gevent.pywsgi.WSGIServer` as `handler_class`.\n\n\n### `gevent_ws.WebSocket`\n\nYou get this object by accessing `wsgi.websocket` property of the environment object. If it exists, it's a websocket connection; if it doesn't, it's an HTTP request. You can use `\"wsgi.websocket\" in env` to check this and route the request correctly.\n\n\n### `gevent_ws.WebSocket.receive()`\n\nWaits for a message and returns it, either as `str` or `bytes`. Blocks. May return `None` if the connection is closed or an `OSError` if the socket can't be read from.\n\n\n### `gevent_ws.WebSocket.receive_nowait()`\n\nReturns the message if it's available (the format is the same as in `receive()`) or `None` if no message is in the queue. May return `None` or raise `OSError` (see `receive()`).\n\n\n### `gevent_ws.WebSocket.send(message)`\n\nSends a message to the other party. `message` can be either `str` or `bytes`. May raise `EOFError` if the connection is closed or `OSError` if the message can't be sent for some other reason.\n\n\n### `gevent_ws.WebSocket.close(status=1000)`\n\nCloses the websocket. Status `1000` (the default one) means that the connection is closed cleanly. Check [RFC](https://tools.ietf.org/html/rfc6455#section-7.4) for more status codes.\n\n\n### `gevent_ws.WebSocket.set_max_message_length(length)`\n\nSet maximum incoming message size (in bytes). 10 MiB is the default value.\n\n\n### `gevent_ws.WebSocket.closed`\n\nA boolean showing whether the connection is closed (by any of the two parties) or is being closed.\n\n\n### `gevent_ws.WebSocket.status`\n\nThe close status code sent by the other party. `None` if the socket was closed by the client, the server didn't return the error code or the connection was aborted abnormally.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurplesyringa%2Fgevent-ws","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpurplesyringa%2Fgevent-ws","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurplesyringa%2Fgevent-ws/lists"}