Files
fn_registry/python/functions/infra/http_replay_sequence.md
T
egutierrez 8742cb25be feat(browser): auto-commit con 60 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-07 11:42:31 +02:00

6.2 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, params, output
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path params output
http_replay_sequence function py infra 1.0.0 impure def http_replay_sequence(calls: list[dict], *, params: dict | None = None, extract: list[dict] | None = None, timeout_s: float = 30.0, verify_tls: bool = True, allow_redirects: bool = True, base_headers: dict | None = None) -> dict Motor de replay HTTP: ejecuta en orden una secuencia de call specs (las que produce har_extract_calls_py_cybersecurity) compartiendo una sesion (cookie jar) entre pasos, con substitucion de parametros {{param}} y extraccion de valores de una respuesta para usarlos en pasos siguientes (p.ej. token CSRF del GET inicial -> header del POST). Pieza reutilizable del Nivel 1 (HTTP puro) del patron grabar->destilar->reproducir.
flow-replay
http
replay
client
infra
false error_go_core
re
requests
true
test_golden_extract_and_subst
test_edge_missing_param
test_error_path_request_exception
python/functions/infra/http_replay_sequence_test.py python/functions/infra/http_replay_sequence.py
name desc
calls Lista ordenada de call specs. Cada spec: {method, url, headers(dict), cookies(dict opc), body(str|None), body_type:'json'|'form'|'raw'|None}. El body ya es texto (no se re-serializa). Es el formato de salida de har_extract_calls_py_cybersecurity.
name desc
params Dict inicial de contexto para la substitucion {{param}}. Se copia (no se muta el original). Pasa aqui secretos/tokens desde un vault/pass, nunca hardcodeados en los call specs.
name desc
extract Lista de reglas de extraccion {from: int|'last', type: 'json'|'regex'|'header'|'set_cookie', expr: str, as: str}. Se aplican justo tras ejecutar el step indicado en 'from' ('last' = el step recien ejecutado) y guardan el valor en ctx[as] para los pasos siguientes.
name desc
timeout_s Timeout por request en segundos (default: 30.0).
name desc
verify_tls Verificar certificados TLS; se setea en la sesion (default: True). No desactivar salvo entorno de pruebas controlado.
name desc
allow_redirects Si los requests siguen redirects (default: True).
name desc
base_headers Headers por defecto que se mezclan en la sesion (se aplican a todos los pasos). Util para User-Agent / Accept comunes.
Dict {status: 'ok'|'error', steps: [{idx, method, url, status_code, ok, extracted, missing_params, error}], params_final: dict (ctx tras todos los pasos), error: str}. status='error' solo ante excepcion de transporte (requests.RequestException) o entrada invalida; en ese caso corta y deja de ejecutar. Un 4xx/5xx NO corta: el step queda con ok=False y status global sigue 'ok'.

Ejemplo

from infra import http_replay_sequence

# Requiere red: usa httpbin.org (publico). 2 pasos:
#   1) GET /uuid          -> extrae el uuid del JSON como param "u"
#   2) POST /anything     -> manda header X-Token: {{u}} (el uuid del paso 1)
calls = [
    {"method": "GET", "url": "https://httpbin.org/uuid",
     "headers": {"Accept": "application/json"}, "body": None, "body_type": None},
    {"method": "POST", "url": "https://httpbin.org/anything",
     "headers": {"X-Token": "{{u}}", "Content-Type": "application/json"},
     "body": '{"hello": "world"}', "body_type": "json"},
]
extract = [
    {"from": 0, "type": "json", "expr": "uuid", "as": "u"},
]

result = http_replay_sequence(calls, extract=extract)

print(result["status"])                       # "ok"
token = result["params_final"]["u"]           # el uuid extraido del paso 0
print("token:", token)
# httpbin /anything devuelve los headers que recibio; comprobamos que el
# paso 2 llevo el valor substituido:
print(result["steps"][1]["status_code"])      # 200
print(result["steps"][1]["ok"])               # True
# El header X-Token: {{u}} se substituyo por el uuid antes de enviarse.

Cuando usarla

Usala tras har_extract_calls_py_cybersecurity, para validar que un flujo capturado se reproduce SIN navegador (Nivel 1 del patron grabar->destilar->reproducir). Es la base de las funciones-accion guardadas en el registry: cuando una secuencia HTTP demuestra reproducir un login + accion, se promueve a una funcion/pipeline dedicada. Tambien sirve para encadenar requests dependientes (token CSRF, session id, paginacion con cursor) compartiendo cookie jar y propagando valores entre pasos.

Gotchas

  • Seguridad — secretos via params, nunca hardcodeados. Los call specs pueden contener cookies/tokens. El caller debe inyectarlos via {{param}} desde un vault/pass (params={...}), no escribirlos en los specs ni commitearlos.
  • Seguridad — replay con efectos es PELIGROSO. Reproducir una secuencia con efectos (POST que reinicia un server, borra, paga, envia) ejecuta esos efectos de verdad. El caller debe confirmar antes de lanzar una secuencia mutante.
  • Seguridad — verify_tls default True. No lo pongas en False salvo en un entorno de pruebas controlado; desactivar la verificacion TLS abre la puerta a MITM.
  • Extraccion JSON es dot-path simple, NO jsonpath completo. "data.items.0.token" funciona (claves + indices de lista por digito), pero no hay filtros, wildcards ni expresiones. Para casos complejos, usa type: regex o post-procesa.
  • Sigue redirects por defecto (allow_redirects=True). Si la secuencia capturada depende del 302 explicito (p.ej. para leer el Location o una cookie intermedia), pon allow_redirects=False.
  • Params faltantes NO abortan. Si un {{nombre}} no esta en ctx, se deja el literal {{nombre}} y se anade a step.missing_params. El request se envia igual; solo una excepcion de transporte corta la ejecucion.
  • El body no se re-serializa. body_type: "json" solo documenta el tipo; el body ya es texto y se manda como data=body. Asegurate de incluir el header Content-Type adecuado en el spec.
  • 4xx/5xx no es error global. El step queda ok=False con su status_code, pero status global sigue "ok". Solo requests.RequestException (DNS, conexion, timeout) marca status="error" y corta.

Capability growth log

v1.0.0 — version inicial.