Python SDK for rstream tunnels.
Project description
rstream Python SDK
rstreamlabs-rstream is the Python SDK for rstream tunnels and webhook
receivers. Python code imports it as rstream.
The SDK is async-first, framework-neutral, and uses the same runtime protocol and CLI-compatible configuration model as the Go, JavaScript, Java, and C++ SDKs. It is designed for Python services that need to publish local HTTP applications, dial private tunnels, accept bytestream tunnel connections directly, or verify rstream webhook deliveries in a backend framework.
SDK Surface
This repository targets Python 3.10 and newer.
The first public release focuses on the Python-native surface that is ready for production use:
| Area | Supported |
|---|---|
| Runtime client | Async control-channel client |
| Published tunnels | HTTP/1.1 bytestream tunnels |
| Private tunnels | Dial by tunnel name or ID |
| Local forwarding | BytestreamTunnel.forward_to(host, port) |
| Direct accept | await tunnel.accept() and async iteration |
| ASGI helper | Direct HTTP/1.1 bridge for ASGI apps |
| WSGI helper | Direct HTTP/1.1 bridge for WSGI apps |
| Webhooks | Signature generation, verification, and event parsing |
| Config | CLI-compatible YAML config and environment variables |
Datagram tunnels, QUIC runtime transport, HTTP/3 tunnel creation, custom transport proxies, and external credential stores are rejected explicitly by this SDK version instead of being ignored.
Install
pip install rstreamlabs-rstream
For ASGI/FastAPI helpers:
pip install "rstreamlabs-rstream[asgi]"
For WSGI/Flask/Django helpers:
pip install "rstreamlabs-rstream[wsgi]"
For managed project endpoint discovery through the Control plane API:
pip install "rstreamlabs-rstream[api]"
For local example applications:
pip install "rstreamlabs-rstream[examples]"
Configuration
The SDK reads the same config file as the CLI by default:
~/.rstream/config.yaml
Configuration is resolved in this order:
- Explicit
Client(...)options. - Environment variables.
- The selected context in the config file.
- SDK defaults.
Environment variables
| Variable | Purpose |
|---|---|
RSTREAM_CONFIG |
Override the config file path. |
RSTREAM_CONTEXT |
Select a context from the config file. |
RSTREAM_ENGINE |
Use an explicit engine host and optional port. |
RSTREAM_AUTHENTICATION_TOKEN |
Use an explicit authentication token. |
RSTREAM_MTLS_CERT_FILE |
Client certificate file for mTLS authentication. |
RSTREAM_MTLS_KEY_FILE |
Client private key file for mTLS authentication. |
RSTREAM_API_URL |
Control plane API URL for managed project discovery. |
RSTREAM_ENGINE_ADDRESS is also accepted for compatibility with older local
SDK workflows. Prefer RSTREAM_ENGINE in new code.
See docs/CONFIGURATION.md for supported YAML fields and error behavior.
FastAPI tunnel
import asyncio
from fastapi import FastAPI
import rstream
app = FastAPI()
@app.get("/")
async def root() -> dict[str, str]:
return {"status": "ok"}
async def main() -> None:
async with (
rstream.Client.from_env() as client,
await client.connect() as control,
):
tunnel = await control.create_tunnel(
protocol="http",
http_version="http/1.1",
publish=True,
)
print("Forwarding address:", tunnel.forwarding_address)
await rstream.asgi.serve(app, tunnel)
asyncio.run(main())
The ASGI helper parses accepted rstream streams and dispatches them to the app in-process. It does not start a loopback server.
Local forwarding
forward_to() remains available for existing services that already listen on a
local TCP port:
await tunnel.forward_to("127.0.0.1", 8000)
It keeps accepting rstream streams and relays them to the local TCP service until the tunnel or control channel is closed.
Private dial
import asyncio
import rstream
async def main() -> None:
async with (
rstream.Client.from_env() as client,
await client.dial("private-api") as stream,
):
stream.write(b"ping")
await stream.drain()
print(await stream.read(1024))
asyncio.run(main())
Private tunnels are addressed by name or ID. They do not expose a public forwarding address.
Webhook receiver
from fastapi import Request
import rstream
async def handle_webhook(request: Request) -> None:
payload = await request.body()
signature = request.headers["rstream-signature"]
secret = "whsec_..."
event = rstream.verify_event(payload, signature, secret)
resource_id = event.object.get("id")
if event.type == "tunnel.created":
print("Tunnel is online:", resource_id)
event.id is suitable for idempotency. Keep the raw request body unchanged when
verifying the signature.
See docs/WEBHOOKS.md for the payload shape and headers.
Examples
| Example | Purpose |
|---|---|
| examples/forward-local-port | Publish an existing local TCP service. |
| examples/private-dial | Dial a private tunnel by name or ID. |
| examples/fastapi-tunnel | Publish a FastAPI app through the direct ASGI helper. |
| examples/flask-tunnel | Publish a Flask app through the direct WSGI helper. |
| examples/django-tunnel | Publish a Django app through the direct WSGI helper. |
| examples/aiohttp-local-forwarding | Publish an aiohttp app through managed local forwarding. |
| examples/webhook-receiver | Verify webhook deliveries inside a FastAPI route. |
| examples/flask-webhook-receiver | Verify webhook deliveries inside a Flask route. |
| examples/django-webhook-receiver | Verify webhook deliveries inside a Django view. |
Development
python -m venv .venv
. .venv/bin/activate
pip install -e ".[dev]"
ruff check .
ruff format --check .
mypy
pytest
python -m build
Real-engine tests are opt-in:
RSTREAM_PYTHON_E2E=1 pytest tests/e2e
See docs/TESTING.md for local-engine and managed-environment test commands.
Repository setup and release
The intended GitHub repository is rstreamlabs/rstream-python. CI requires no
secret for normal pull request checks. Release automation uses release-please and
requires the maintainer-managed RELEASE_PLEASE_TOKEN secret plus the
CI_ALLOWED_ACTOR repository variable.
See docs/GITHUB_SETUP.md before creating or publishing the repository.
License
Apache-2.0. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rstreamlabs_rstream-0.1.1.tar.gz.
File metadata
- Download URL: rstreamlabs_rstream-0.1.1.tar.gz
- Upload date:
- Size: 60.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
058b6d22e24d10a8ec5b0a637a9e7c92ab014994229d128e80d000d9c904d021
|
|
| MD5 |
38c63e94ca6b7d6cc188352ff7097b98
|
|
| BLAKE2b-256 |
887230923943685a2b1f929482cd82a68f9b55b1ac717c1e6c4a43887e171f0f
|
Provenance
The following attestation bundles were made for rstreamlabs_rstream-0.1.1.tar.gz:
Publisher:
publish.yml on rstreamlabs/rstream-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rstreamlabs_rstream-0.1.1.tar.gz -
Subject digest:
058b6d22e24d10a8ec5b0a637a9e7c92ab014994229d128e80d000d9c904d021 - Sigstore transparency entry: 1839128021
- Sigstore integration time:
-
Permalink:
rstreamlabs/rstream-python@1317c9ebc9e22eeead1beac40c727b97cc27ec98 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/rstreamlabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1317c9ebc9e22eeead1beac40c727b97cc27ec98 -
Trigger Event:
release
-
Statement type:
File details
Details for the file rstreamlabs_rstream-0.1.1-py3-none-any.whl.
File metadata
- Download URL: rstreamlabs_rstream-0.1.1-py3-none-any.whl
- Upload date:
- Size: 42.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b616944ae19ffb663405b584d87285059a06ade0eaec39d09e31d4ea02dd0967
|
|
| MD5 |
73ef53fc0855a2d79925a3427b94dac1
|
|
| BLAKE2b-256 |
6a5be6729bc3cecbf9bf37131e8657e0858387e304038d4e5f6e32056cb323f7
|
Provenance
The following attestation bundles were made for rstreamlabs_rstream-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on rstreamlabs/rstream-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rstreamlabs_rstream-0.1.1-py3-none-any.whl -
Subject digest:
b616944ae19ffb663405b584d87285059a06ade0eaec39d09e31d4ea02dd0967 - Sigstore transparency entry: 1839128046
- Sigstore integration time:
-
Permalink:
rstreamlabs/rstream-python@1317c9ebc9e22eeead1beac40c727b97cc27ec98 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/rstreamlabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1317c9ebc9e22eeead1beac40c727b97cc27ec98 -
Trigger Event:
release
-
Statement type: