Framework ligero HTTP + WebSocket.
Project description
wsbuilder
wsbuilder es un paquete Python para construir servidores HTTP + WebSocket sin dependencias externas.
Lightweight Python HTTP + WebSocket framework for building real-time APIs and custom servers.
Keywords: python, http-server, websocket, framework, real-time, api, socket.
Incluye
wsbuilder.framework: router, request/response, servidor HTTP, handshake WS y utilidades de frames.wsbuilder.orm: ORM flexible para SQLite3 (modelos, QuerySet, filtros, transacciones anidadas).wsbuilder.dns: DNS UDP local minimo para registroslocalhost.wsbuilder.cookies/wsbuilder.headers: utilidades para cookies y headers HTTP.wsbuilder.ws_demo: demo completo HTTP + WebSocket + REST + SQLite.
Documentacion completa
- Ver docs/README.md para arquitectura, API, seguridad, CI/CD, testing y guias de uso.
Instalacion local
python -m pip install -e .
Uso rapido del framework
from wsbuilder import App, Response, parse_close_payload
app = App()
@app.view("/")
def home(_request):
return Response.html("<h1>wsbuilder</h1>")
@app.api("/api/health")
def health(_request):
return {"ok": True}
@app.ws("/ws/")
def ws_handler(ws, _request):
while True:
fin, opcode, payload, _masked, _mask = ws.recv_frame()
if opcode == 0x8:
code, reason = parse_close_payload(payload)
ws.close(code or 1000, reason or "")
break
if opcode == 0x9:
ws.send_pong(payload)
continue
if opcode == 0x1:
ws.send_text(payload.decode("utf-8", errors="ignore"))
elif opcode == 0x2:
ws.send_binary(payload)
app.run("0.0.0.0", 8765)
Para CORS sin variables de entorno:
app = App(cors_allow_origin="*")
Thread Pool en Views
Las view por defecto se ejecutan en el hilo padre (thread_count=0).
Puedes configurar un pool por ruta con min/max de hilos y limite de requests por hilo:
from wsbuilder import App
app = App()
@app.view("/jobs", min_threads=1, max_threads=4, requests_per_thread=0)
def jobs(_request):
return "ok"
min_threads: workers iniciales para laview.max_threads: tope de workers para esaview(0deshabilita pool).requests_per_thread: capacidad por worker (0= sin limite).- Distribucion: siempre por
least_busy(worker menos ocupado). - Se expone metadata de worker en headers y metrics (
/api/metrics,/api/metrics/stream).
ORM SQLite3 rapido
from wsbuilder import Database, IntegerField, Model, TextField
class User(Model):
id = IntegerField(primary_key=True, auto_increment=True)
username = TextField(unique=True, index=True, null=False)
email = TextField(null=False)
db = Database("app.db")
User.create_table(db)
u = User(username="alice", email="alice@example.com")
u.save(db)
admins = User.objects(db).filter(username__contains="ali").order_by("-id").all()
print([x.to_dict() for x in admins])
Metrics (JSON stream)
from wsbuilder import App
app = App()
app.enable_metrics() # crea /api/metrics y /api/metrics/stream
Probar snapshot:
curl http://127.0.0.1:8765/api/metrics
Probar stream NDJSON:
curl -N "http://127.0.0.1:8765/api/metrics/stream?interval=1&limit=5"
Modo continuo (no termina solo):
curl -N "http://127.0.0.1:8765/api/metrics/stream?interval=1&follow=1"
DNS local minimo
from wsbuilder import LocalDNSServer
dns = LocalDNSServer() # default: 127.0.0.1:5533
dns.start()
# ...
dns.close()
HTTP streaming (chunked)
import time
from wsbuilder import App, Response
app = App()
@app.view("/stream")
def stream(_request):
def chunks():
for i in range(5):
yield f"chunk {i}\n"
time.sleep(1)
return Response.stream(chunks(), content_type="text/plain; charset=utf-8")
Ejecutar demo incluido
python -m wsbuilder --host 0.0.0.0 --port 8765
# o
wsbuilder --host 0.0.0.0 --port 8765
Configuracion CORS
- Usa
App(cors_allow_origin="https://tu-dominio.com"). - Usa
App(cors_allow_origin="*")para permitir cualquier origen.
CI/CD (GitHub Actions)
package-build.yml: construyesdist+wheel, valida metadata y prueba instalacion/import.release-from-main.ymlen push amain: calculasemverautomaticamente, crea ramarelease/v<version>desdemain, actualiza version del paquete, crea tagv<version>y publica GitHub Release.publish-packages.ymlen push de tagv*: construye y publica a PyPI/TestPyPI (instalable conpip).publish-packages.ymlen tagsv*: adjunta los paquetes al GitHub Release.main-only-from-develop.yml(workflowmain-pr-source-check): valida metadata minima del PR haciamain.
Reglas de versionado automatico
major: si algun commit traeBREAKING CHANGE,type(scope)!:o ramas/commits marcados comobreaking/major.minor: si hay suficiente peso defeat/feature(proporcional frente a cambiospatch) y no haymajor.patch: cualquier otro caso.
Recomendado usar Conventional Commits para que el calculo de version sea preciso.
Secrets requeridos
RELEASE_BOT_TOKEN(recomendado): PAT/fine-grained token para crear ramarelease/*, crear tag y publicar GitHub Release.RULESET_ADMIN_TOKEN(fallback): usado automaticamente si no existeRELEASE_BOT_TOKEN.PYPI_API_TOKEN: token de publicacion para PyPI.TEST_PYPI_API_TOKEN(opcional): token de publicacion para TestPyPI.
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 wsbuilder-0.9.0.tar.gz.
File metadata
- Download URL: wsbuilder-0.9.0.tar.gz
- Upload date:
- Size: 76.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a43424d97cbb03be557f83b6b557f5ddb2839ca594ed751ed26c08bb75642385
|
|
| MD5 |
058d25e6f2fb1f258b2dd5d4c0a0260f
|
|
| BLAKE2b-256 |
71ba550d7088c94503048189be779f8980ef9382d02697920511f65b8fc22d19
|
File details
Details for the file wsbuilder-0.9.0-py3-none-any.whl.
File metadata
- Download URL: wsbuilder-0.9.0-py3-none-any.whl
- Upload date:
- Size: 73.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
568bb95830dde4cce7a9b0d83d82b3237b81bb222d83b05e960ce88a63cccd0c
|
|
| MD5 |
c8cec5de1c430e67a3b02d74c32aa6db
|
|
| BLAKE2b-256 |
69fb572b76bb085562a85c9396cc9cd28776528e11a866ffa53b9896cbf85666
|