Files
fn_registry/python/functions/infra/render_caddyfile.md
T
egutierrez 32c7336bf6 feat(infra): auto-commit con 56 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-21 14:22:55 +02:00

4.5 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports params output tested tests test_file_path file_path
render_caddyfile function py infra 1.1.0 pure def render_caddyfile(services: list[dict], dashboard: dict | None = None) -> str Parte del sistema local_hub: transforma una lista de servicios normalizados en el texto de un fragmento de Caddyfile que mapea cada subdominio *.localhost a su puerto local via reverse_proxy HTTP plano (loopback, sin TLS). Cada servicio es un dict con subdomain (str) y port (int); el resto de claves se ignoran. Los bloques de servicio se ordenan por subdominio alfabetico para que la salida sea estable y reproducible (clave para diffs y tests). Un dashboard opcional emite su bloque PRIMERO porque es la pagina principal. Ignora servicios sin subdomain o sin port (los salta, no lanza) y no deduplica. Pura: solo stdlib, sin I/O ni red, determinista.
local-hub
caddy
caddyfile
reverse-proxy
infra
python
false
name desc
services lista de dicts de servicio normalizados. Cada uno debe tener al menos subdomain (str, sin el sufijo .localhost) y port (int, puerto local). Otras claves se ignoran. Los servicios sin subdomain o sin port se saltan silenciosamente. No se deduplica: eso es trabajo del discover.
name desc
dashboard dict opcional {subdomain, port} para la pagina principal del hub (ej. {"subdomain": "home", "port": 8585}). Si se pasa, su bloque va el primero de la salida. None = no se emite bloque de dashboard. Si le falta subdomain o port, se ignora igual que un servicio invalido.
string con el Caddyfile completo: empieza por una cabecera de comentario (# Generado por render_caddyfile_py_infra ...), luego el bloque del dashboard si aplica, y despues los bloques de servicio ordenados alfabeticamente por subdominio. Cada bloque es 'http://<subdomain>.localhost {\n reverse_proxy 127.0.0.1:<port>\n}\n' con 4 espacios de indentacion. La salida termina con un unico \n. true
test_golden_dos_servicios_ordenados
test_dashboard_va_primero
test_lista_vacia_solo_cabecera
test_servicio_sin_port_se_ignora
test_servicio_sin_subdomain_se_ignora
test_rewrite_host_emite_header_up
test_rewrite_host_ausente_o_falso_no_reescribe
python/functions/infra/render_caddyfile_test.py python/functions/infra/render_caddyfile.py

Ejemplo

import sys, os
sys.path.insert(0, os.path.join("python", "functions", "infra"))
from render_caddyfile import render_caddyfile

services = [
    {"subdomain": "metabase", "port": 3030},
    {"subdomain": "grafana", "port": 3000},
]
dashboard = {"subdomain": "home", "port": 8585}

print(render_caddyfile(services, dashboard=dashboard))
# # Generado por render_caddyfile_py_infra — NO editar a mano. Fuente: apps/local_hub/local_services.yaml
# http://home.localhost {
#     reverse_proxy 127.0.0.1:8585
# }
# http://grafana.localhost {
#     reverse_proxy 127.0.0.1:3000
# }
# http://metabase.localhost {
#     reverse_proxy 127.0.0.1:3030
# }

Cuando usarla

Cuando, dentro del sistema local_hub, ya tienes la lista de servicios locales normalizada (cada uno con su subdomain y port) y necesitas materializar el fragmento de Caddyfile que enruta *.localhost a sus puertos. Usala justo antes de escribir el archivo a disco y recargar Caddy: esta funcion solo produce el texto (pura), el I/O y el reload van en una funcion impura o pipeline aparte. Tambien util para tests/diffs porque la salida es determinista (bloques ordenados por subdominio).

Gotchas

  • El formato es HTTP plano a proposito (http://..., sin TLS): todo el trafico es loopback (127.0.0.1), no hay nada que cifrar y *.localhost no necesita certificado. No es un bug.
  • No deduplica subdominios: si dos servicios comparten subdomain, ambos bloques se emiten y Caddy se quedara con el ultimo. La deduplicacion es responsabilidad del discover que produce services.
  • rewrite_host solo cambia la cabecera Host que ve el upstream, no la URL que abre el usuario. Actívalo unicamente para servicios que validan el header y rechazan el subdominio (Jupyter devuelve 400, algunos FastAPI/uvicorn con --forwarded-allow-ips estricto). Para el resto dejalo ausente/False: añadir header_up Host sin necesidad puede romper virtual-hosting del upstream.

Capability growth log

  • v1.1.0 (2026-06-20) — añade soporte rewrite_host (header_up Host) para servicios que validan el header Host