61ec4c8a76
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.
135 lines
4.9 KiB
Markdown
135 lines
4.9 KiB
Markdown
---
|
|
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<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:
|
|
|
|
```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.
|