Files
fn_registry/dev/issues/completed/0110-cpp-http-client-helper.md
egutierrez 0e1b3e3aa0 docs: cerrar issue 0110 (http_request + http_get_json cpp/core)
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.
2026-05-18 18:15:38 +02:00

4.9 KiB

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0110 Gap registry: helper HTTP cliente C++ (curl/popen) reutilizable pendiente feature
cpp-stack
registry-quality
registry media
0111
0106
2026-05-18 2026-05-18
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)

namespace fn_http {
    struct Request {
        std::string method;        // "GET", "POST", "PUT", "DELETE"
        std::string url;
        std::vector<std::pair<std::string,std::string>> headers;
        std::string body;           // raw bytes (JSON, etc.)
        int timeout_ms = 5000;
        std::string bearer_token;   // shortcut: anade Authorization: Bearer <token>
        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<std::pair<std::string,std::string>> 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:

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.