feat(recon): modo CDP en fingerprint_web_stack para detectar SPAs
Añade fetch_http_fingerprint_cdp_py_browser (domain browser): recoge el HTML renderizado tras ejecutar JavaScript usando un Chrome remoto via CDP, componiendo cdp_open_url_and_wait + cdp_eval. Devuelve la misma estructura que el fetch estático para que detect_web_tech lo consuma sin cambios. Integra use_cdp en el pipeline fingerprint_web_stack (v1.1.0): combina los headers reales del fetch estático con el HTML post-JS del CDP. Detecta frameworks de SPA (React/Vue/Angular/Next) que el fetch estático no ve porque montan el DOM en runtime. Si no hay Chrome en cdp_port, degrada al fetch estático con un warning (no rompe). cdp_port=9333 (Chrome aislado) recomendado para terceros, 9222 diario. Verificado en vivo (Chrome 9333): sobre una SPA cuyo marcador de framework solo aparece tras ejecutar JS, el estático detecta solo nginx; con use_cdp=True detecta además Next.js, React y Node.js. Tests: 48 verdes (error path sin Chrome + happy path mockeado + degradación). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -178,3 +178,44 @@ def test_fetch_fallido_propaga_error_sin_red():
|
||||
assert result["fetch"]["status"] == "error", result
|
||||
# No se intento archivar nada.
|
||||
assert save_called["n"] == 0, save_called
|
||||
|
||||
|
||||
# --- 4. use_cdp sin Chrome: DEGRADA a estatico con warning (no falla) ---------
|
||||
|
||||
def test_use_cdp_sin_chrome_degrada_a_estatico():
|
||||
"""use_cdp=True sin Chrome (cdp_port=1) degrada al fetch estatico con warning.
|
||||
|
||||
Levanta el mismo HTTPServer WordPress/nginx/PHP local que el golden y pide
|
||||
use_cdp con cdp_port=1 (donde no hay ningun Chrome escuchando). El fetch CDP
|
||||
falla, el pipeline NO rompe: usa el HTML estatico, marca html_source=static,
|
||||
rellena warnings y sigue detectando WordPress/nginx por el html/headers.
|
||||
"""
|
||||
httpd, port, thread = _start_wp_server()
|
||||
try:
|
||||
result = fingerprint_web_stack(
|
||||
f"http://127.0.0.1:{port}/",
|
||||
timeout_s=5.0,
|
||||
save=False,
|
||||
use_cdp=True,
|
||||
cdp_port=1, # puerto sin Chrome: el fetch CDP falla -> degrada
|
||||
wait_render_s=0.0,
|
||||
)
|
||||
finally:
|
||||
httpd.shutdown()
|
||||
httpd.server_close()
|
||||
thread.join(timeout=2.0)
|
||||
|
||||
# Degrado, no fallo.
|
||||
assert result["status"] == "ok", result
|
||||
# Cayo al HTML estatico (CDP no disponible).
|
||||
assert result["html_source"] == "static", result
|
||||
assert result["rendered"] is False, result
|
||||
# Hubo warning de degradacion.
|
||||
assert result["warnings"], result
|
||||
assert any("cdp no disponible" in w for w in result["warnings"]), result["warnings"]
|
||||
# La deteccion estatica sigue funcionando.
|
||||
names = {t["name"] for t in result["technologies"]}
|
||||
assert "WordPress" in names, names
|
||||
assert "nginx" in names, names
|
||||
# No se archivo (save=False).
|
||||
assert result["saved"] is None, result
|
||||
|
||||
Reference in New Issue
Block a user