From 61ec4c8a76a2d0747328b85304a0f31cbcaede79 Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Mon, 18 May 2026 18:15:38 +0200 Subject: [PATCH] docs: cerrar issue 0110 (http_request + http_get_json cpp/core) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Funciones implementadas, registradas en registry.db via fn index, tests locales (11 cases, 27 assertions) en verde. Cierra el gap detectado: patron curl-popen inline duplicado en services_monitor / dag_engine_ui / data_factory ahora promovido al registry. Sigue habilitando issue 0111 (apps/process_explorer http_client) cuando arranque — usara http_request_cpp_core directamente. --- .../completed/0110-cpp-http-client-helper.md | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 dev/issues/completed/0110-cpp-http-client-helper.md diff --git a/dev/issues/completed/0110-cpp-http-client-helper.md b/dev/issues/completed/0110-cpp-http-client-helper.md new file mode 100644 index 00000000..df4bd17d --- /dev/null +++ b/dev/issues/completed/0110-cpp-http-client-helper.md @@ -0,0 +1,134 @@ +--- +id: "0110" +title: "Gap registry: helper HTTP cliente C++ (curl/popen) reutilizable" +status: pendiente +type: feature +domain: + - cpp-stack + - registry-quality +scope: registry +priority: media +depends: [] +blocks: + - "0111" +related: + - "0106" +created: 2026-05-18 +updated: 2026-05-18 +tags: [http, cpp, registry-gap, curl, helper] +--- + +# 0110 — Helper HTTP cliente C++ en el registry + +## Problema + +Hoy no existe funcion HTTP cliente reutilizable en `cpp/functions/`. Cada app C++ que necesita +golpear un endpoint reinventa la capa: + +| App | Fichero | Tecnica | LOC aprox | +|---|---|---|---| +| `apps/services_monitor/` | `http_client.cpp` | cURL popen/WinHTTP segun plataforma | ~150 | +| `apps/dag_engine_ui/` | inline en `main.cpp` | curl CLI via popen + parse | ~80 | +| `apps/data_factory/` | inline | popen curl | ~60 | +| `cpp/functions/core/llm_anthropic.cpp` | propio | cURL popen — solo Anthropic | — | +| `apps/process_explorer/` (issue 0111) | `http_client.cpp` local | pendiente — clonara services_monitor | ~150 esperados | + +El patron ya supera el umbral `>2x` que dispara la regla de promocion (CLAUDE.md +"Si patron se repite >2x → propose nueva funcion via fn-constructor"). Cada app duplica: + +- Detection de plataforma (Linux: `popen("curl -s ...")`, Win: `WinHTTPOpen`/popen) +- Manejo de basicAuth / Bearer tokens +- Timeouts +- Captura de body + status code +- Manejo de errores transitorios (DNS, conexion rechazada) + +## Decision + +Anadir al registry dos funciones C++ en dominio `core` (o `infra`): + +### `http_request_cpp_core` (impure) + +```cpp +namespace fn_http { + struct Request { + std::string method; // "GET", "POST", "PUT", "DELETE" + std::string url; + std::vector> headers; + std::string body; // raw bytes (JSON, etc.) + int timeout_ms = 5000; + std::string bearer_token; // shortcut: anade Authorization: Bearer + std::string basic_user; // shortcut: anade Authorization: Basic base64(user:pass) + std::string basic_pass; + }; + struct Response { + int status = 0; // 0 = error de transporte + std::string body; + std::vector> headers; + std::string error; // vacio si OK + int64_t duration_ms = 0; + }; + Response request(const Request& req); +} +``` + +Implementacion: cURL via popen (portable WSL+Win+Linux, igual que `llm_anthropic`). +Si en el futuro queremos rendimiento real, swap a libcurl linkado estaticamente +o WinHTTP via `#ifdef _WIN32` — interfaz Request/Response no cambia. + +### `http_get_json_cpp_core` (impure, pure wrapper) + +Helper que envuelve `http_request` + parse JSON (via `nlohmann::json` o similar +ya disponible en el repo) para los casos comunes: + +```cpp +namespace fn_http { + // Devuelve parsed JSON o lanza si status != 2xx + nlohmann::json get_json(const std::string& url, + const std::string& bearer_token = "", + int timeout_ms = 5000); +} +``` + +## Plan de migracion + +Tras crear las funciones, abrir issue separado por cada consumer para migrar: + +1. `apps/services_monitor/http_client.cpp` -> usar `fn_http::request` +2. `apps/dag_engine_ui/main.cpp` (inline) +3. `apps/data_factory/` (inline) +4. `cpp/functions/core/llm_anthropic.cpp` — refactor para usar `fn_http::request` por + debajo (mantiene API publica) +5. `apps/process_explorer/` (issue 0111) — nace ya usando el helper + +## Criterios de aceptacion + +- [ ] `cpp/functions/core/http_request.{cpp,h,md}` registrado en `registry.db` +- [ ] `cpp/functions/core/http_get_json.{cpp,h,md}` idem +- [ ] Tests visuales o de integracion contra `httpbin.org` (200/404/timeout/auth) +- [ ] Frontmatter completo (`params`/`output`/`tags`/`example`) +- [ ] `.md` cumple contrato self-doc (`## Ejemplo`, `## Cuando usarla`, `## Gotchas`) +- [ ] Al menos 1 consumer migrado para validar API (recomendado `services_monitor`) +- [ ] `fn doctor uses-functions` limpio + +## Gotchas conocidos + +- cURL popen en Windows necesita `curl.exe` en PATH — todos los WSL/Win lo tienen, + pero documentar en `## Gotchas`. +- Bodies binarios: popen complica el escape; primera version solo string bodies. +- TLS verify: por defecto on; permitir `req.insecure = true` solo para testing. +- Timeouts: cURL `--max-time` cubre handshake+transfer; documentar diferencia con + read-timeout puro. + +## Por que no usar libcurl linkado + +- `popen("curl ...")` no requiere anadir libcurl al toolchain MinGW cross-compile + (que ya costo configurar). `llm_anthropic` lleva meses funcionando asi. +- Cuando aparezca un caso real de latencia (>10 req/s sostenido), abrimos issue + separado para swap a libcurl. + +## Out of scope (no en este issue) + +- WebSocket / SSE — cliente WS C++ es otro gap; abrir issue propio cuando aplique. +- Cliente gRPC. +- Streaming responses (SSE chunk-by-chunk) — usar caso de `dag_engine_ui` para + decidir cuando.