# retoor <retoor@molodetz.nl>
import logging
from fastapi import APIRouter, Request, WebSocket
from starlette.responses import Response
from devplacepy.services.containers import activity, api, forward, store
from devplacepy.services.containers.workspace import naming, tunnels
logger = logging.getLogger(__name__)
router = APIRouter()
METHODS = forward.METHODS
def resolve(host: str):
if not naming.is_tunnel_host(host):
return None, None, None, None
row = tunnels.by_hostname(host)
if not row or row.get("status") not in tunnels.SERVING_STATUSES:
return None, None, None, None
instance = store.get_instance(row.get("instance_uid", ""))
if not instance or instance.get("deleted_at"):
return None, None, None, None
if instance.get("suspended_at"):
return row, instance, None, None
if instance.get("status") != store.ST_RUNNING:
return row, instance, None, None
host, port = api.tunnel_target(instance, int(row.get("container_port") or 0))
return row, instance, host, port
async def handle_http(request: Request, path: str) -> Response:
host = request.headers.get("host", "")
row, instance, gateway, port = resolve(host)
if row is None:
return Response("no tunnel is published at this address", status_code=404)
if instance is not None and instance.get("suspended_at"):
return Response("this workspace is suspended", status_code=403)
if not gateway or not port:
return Response("the tunnel has no reachable port", status_code=502)
return await forward.proxy_http(
request,
gateway,
port,
path,
on_complete=lambda sent: record_traffic(instance["uid"], row["uid"], sent),
)
def record_traffic(instance_uid: str, tunnel_uid: str, sent: int) -> None:
activity.touch(instance_uid, egress_bytes=sent)
tunnels.record_hit(tunnel_uid, sent)
async def handle_ws(websocket: WebSocket, path: str) -> None:
host = websocket.headers.get("host", "")
row, instance, gateway, port = resolve(host)
if row is None or instance is None or not gateway or not port:
await websocket.close(code=1011)
return
activity.touch(instance["uid"])
await forward.proxy_ws(websocket, gateway, port, path)