{"id":51062109,"url":"https://github.com/zeek/zeek-websocket-rs","last_synced_at":"2026-06-23T03:30:38.187Z","repository":{"id":294819979,"uuid":"985530631","full_name":"zeek/zeek-websocket-rs","owner":"zeek","description":"Bindings for Zeek's WebSocket API","archived":false,"fork":false,"pushed_at":"2026-06-22T10:55:20.000Z","size":340,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-06-22T12:24:55.994Z","etag":null,"topics":["c","python","rust","websocket","websocket-client","zeek"],"latest_commit_sha":null,"homepage":"https://zeek.github.io/zeek-websocket-rs/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zeek.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-18T00:53:21.000Z","updated_at":"2026-06-22T10:54:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"c86866fd-8a79-4d7d-a3a0-71b02cf347cb","html_url":"https://github.com/zeek/zeek-websocket-rs","commit_stats":null,"previous_names":["bbannier/zeek-websocket-rs","zeek/zeek-websocket-rs"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zeek/zeek-websocket-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeek%2Fzeek-websocket-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeek%2Fzeek-websocket-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeek%2Fzeek-websocket-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeek%2Fzeek-websocket-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zeek","download_url":"https://codeload.github.com/zeek/zeek-websocket-rs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeek%2Fzeek-websocket-rs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34674702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["c","python","rust","websocket","websocket-client","zeek"],"created_at":"2026-06-23T03:30:34.883Z","updated_at":"2026-06-23T03:30:38.172Z","avatar_url":"https://github.com/zeek.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rust types for interacting with Zeek over WebSocket\n\nThis library provides types for interacting with [Zeek](https://zeek.org)'s\nWebSocket API. See the\n[docs](https://bbannier.github.io/zeek-websocket-rs/zeek_websocket/index.html)\nfor more details.\n\n## Language bindings\n\nWhile this is primarily a Rust library we expose bindings for\n[Python](#python-bindings) and [C](#c-bindings).\n\n### Python bindings\n\nPython bindings are generated with [PyO3](https://github.com/PyO3/pyo3) which\nmakes use of Rust completely transparent to users.\n\nWe provide two ways to interact with Zeek:\n\n- [`ZeekClient`](bindings/python/zeek_websocket/zeek_websocket.pyi) for an\n  asynchronous interface\n- [`Client`](bindings/python/zeek_websocket/__init__.py) for a synchronous\n  interface\n\nIf possible we suggest to use `ZeekClient`.\n\nBoth `ZeekClient` and `Client` allow to receive and send Zeek events as\n[`Event`](bindings/python/zeek_websocket/zeek_websocket.pyi) values.\n\n#### Example: Asynchronous API\n\n```python\n# Connect an asynchronous client to the Zeek WebSocket API endpoint.\nclass Client(ZeekClient):\n    async def connected(self, ack: dict[str, str]) -\u003e None:\n        print(f\"Client connected to endpoint {ack}\")\n\n        # Once connected publish a \"ping\" event.\n        await self.publish(\"/ping\", Event(\"ping\", [\"hi\"], ()))\n\n    async def event(self, topic: str, event: Event) -\u003e None:\n        print(f\"Received {event} on {topic}\")\n\n        # Stop the client once we have seen an event.\n        self.disconnect()\n\n    async def error(self, error: str) -\u003e None:\n        raise NotImplementedError(error)\n\n# Run the client until it either explicitly disconnects, or hits a fatal error.\nawait Service.run(Client(), \"client\", mock_server, [\"/ping\"])\n```\n\n#### Example: Synchronous API\n\n```python\n# Connect a synchronous client to the Zeek WebSocket API endpoint.\nclient = Client(\n    \"client\", endpoint_uri=\"ws://127.0.0.1:80/v1/messages/json\", topics=[\"/topic1\"])\n\n# Try to receive an event. Without explicit `timeout` this blocks until some\n# data was received, but might still return `None`.\n#\n# NOTE: This function should be called regularly if we expect Zeek to send us\n# _any_ data, e.g., if we subscribed to any topics to ensure that messages\n# received by the WebSocket client library are consumed. Otherwise it might\n# overflow which would lead to disconnects.\nif recv := client.receive():\n    topic, event = recv\n    print(f\"Received {event} on {topic}\")\n\n# Publish a `ping` event. This assumes the Zeek-side event is declared as\n#\n#     global ping: event(n: count);\n#\nping = Event(name=\"ping\", args=(4711, ), metadata=())\nclient.publish(topic=\"/topic1\", ping)\n```\n\n#### Mapping data between Python and Zeek WebSocket API types\n\nThe types used in the Zeek WebSocket API do not map one-to-one on native Python\ntypes, so explicit type conversions are required. This library exposes the\n[`Value`](bindings/python/zeek_websocket/__init__.py) type which represents\ndata values understood by the Zeek API. `Value` has a number of base classes\nrepresenting more specific types, e.g., a Zeek `int` is represented as a\n`Value.Integer`,\n\n```python\nprint(f\"{Value.Integer(4711)}\")  # Prints 'Integer(4711)'.\n```\n\nThe full list of supported types is documented in the library's [stub\nfile](bindings/python/zeek_websocket/zeek_websocket.pyi).\n\nThe library provides a convenience function `make_value` which can be used\nto automatically infer a matching `Value` variant,\n\n```python\nprint(f\"{make_value(\"abc\")}\")  # Prints 'String(\"abc\")'.\n```\n\n\u003e [!CAUTION]\n\u003e The Python `int` type holds signed values while Zeek distinguishes between\n\u003e `count` and `int`. To make behavior predicatable `make_value` will always\n\u003e return a `Value.Real` when given a numeric value. Prefer explicit typing if a\n\u003e Zeek events expect a Zeek integer type like `int` or `count`.\n\nWhen creating the `Event` in the previous section we passed arguments `(4711,)`\nwhich also made use of implicit type conversion, and `4711` was implicitly\nmapped to a `Value.Integer`,\n\n```python\nping = Event(name=\"ping\", args=(4711, ), metadata=())\nprint(ping)\n# Event { name: \"ping\", args: [Integer(4711)], metadata: [] }\n```\n\nWe could have been explicit with\n\n```python\nping = Event(name=\"ping\", args=(Value.Integer(4711), ), metadata=())\nprint(ping)\n# Event { name: \"ping\", args: [Integer(4711)], metadata: [] }\n```\n\nA `Value` can be mapped to a native Python value via the `value` attribute,\ne.g.,\n\n```python\nx = make_value(\"abc\")  # Creates a `Value.String`.\nassert x.value == \"abc\"\nassert type(x.value) == str\n```\n\n#### Special handling for Python enums and classes\n\nThe Zeek WebSocket API can represent Zeem `enum` and `record` values, but the\nschema is not part of the protocol's data payload. This is to support cases\nwhere the client might be on a different version of the schema, or might even\nbe completely unaware of the concrete Zeek type. With that the Python bindings\ncan always receive any `enum` or `record` value.\n\nThis still makes inspecting and constructing such values cumbersome, so this\nlibrary provides functionality to convert Zeek `enum` and `record` values to\nnative Python types provided a custom Python type exists.\n\n##### Records\n\nWhile we support constructing a `Value` from any Python class, e.g.,\n\n```python\n# NOTE: Discouraged, see below.\nclass X:\n    def __init__(self, a: int, b: str):\n        self.a = a\n        self.b = b\n\nprint(make_value(X(4711, \"abc\")))  # Prints 'Record({\"a\": Count(4711), \"b\": String(\"abc\")})'.\n```\n\nwe only support converting a `Value` to a Python instances for dataclasses via `as_record`:\n\n```python\n# NOTE: Equivalent to example above, but more powerful.\n@dataclasses.dataclass\nclass X:\n    a: int\n    b: str\n\nx = make_value(X(4711, \"abc\"))  # Record({\"a\": Count(4711), \"b\": String(\"abc\")}).\n\n# Convert to a concrete Python type by providing the target type.\nprint(x.as_record(X))  # Prints 'X(a=4711, b='abc')'.\n```\n\n##### Enums\n\nWe support conversion from an to instances of `enum.Enum` values, e.g.,\n\n```python\nclass E(enum.Enum):\n    a = 1\n    b = 2\n\ne = E.a\n\nx = Value.Enum(e.name)  # Or `make_value(e)`.\n\nassert x.as_enum(E) == E.a\n```\n\n### C bindings\n\nC bindings are dynamically created with\n[cbindgen](https://github.com/mozilla/cbindgen/) and automated for consumption\nwith CMake via [corrosion-rs](https://github.com/corrosion-rs/corrosion). We\nprovide both a static archive as well as a shared library for building in CMake\n`STATIC` or `SHARED` configurations.\n\nA Rust toolchain is required for building the library. We require a fairly\nrecent Rust version, and we suggest installing Rust with\n[rustup](https://rustup.rs/) which is available in many package managers. A\nminimal, but sufficient toolchain can be installed with rustup with\n\n```console\nrustup toolchain install stable --profile minimal\n```\n\nThe repository contains a sample CMake configuration in\n[`bindings/c/examples/`](bindings/c/examples/CMakeLists.txt). For demonstration\nwe also provide sample clients in [C](bindings/c/examples/example.c) and\n[C++](bindings/c/examples/example.cc).\n\nBoth examples include the header file `zeek-websocket.h` provided by the\nlibrary which includes additional documentation. Since it is generated when\nrequired by a dependency it is present in the CMake build folder, likely under\nthe path\n`\u003cBUILD\u003e/_deps/zeekwebsocket-build/corrosion_generated/cbindgen/zeek_websocket_c/include/zeek-websocket.h`.\nIt can be generated by hand by building the target\n`_corrosion_cbindgen_zeek_websocket_c_bindings_zeek_websocket_h`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeek%2Fzeek-websocket-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzeek%2Fzeek-websocket-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeek%2Fzeek-websocket-rs/lists"}