Files
fn_registry/dev/issues/0033-cpp-http-ws-inspector.md
T

5.7 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
0033 C++ http_inspector + websocket_client pendiente feature
cpp-stack
multi-app baja
2026-05-17 2026-05-17

0033 — C++ http_inspector + websocket_client

APP Metadata

Campo Valor
ID 0033
Estado pendiente
Prioridad baja
Tipo feature — C++ core (cpp/functions/core)

Dependencias

text_editor_cpp_core (issue 0025) recomendado para editar bodies; fallback a InputTextMultiline. time_series_buffer_cpp_core.

Desbloquea: debugging visual de APIs internas y feeds en tiempo real desde C++ apps. Util para apps de monitoring que se conectan a servicios propios.


Objetivo

Dos componentes complementarios:

  1. http_inspector_cpp_core — panel ImGui tipo Postman minimo: input URL, dropdown method (GET/POST/PUT/DELETE/PATCH), headers (key/value list), body, boton Send. Muestra status, headers de respuesta, body con pretty-print JSON.
  2. websocket_client_cpp_core — panel WebSocket: input ws://… , botones Connect/Disconnect, area de mensajes (timeline), input para enviar texto, contador msg/s y plot rate.

Vendorea cpp-httplib (MIT, header-only) para HTTP. Para WS usa la API client de cpp-httplib (>=0.20 trae soporte ws basico) o vendorea websocketpp. Decidir en Fase 1.

Demo en primitives_gallery con un endpoint HTTP de prueba (httpbin.org) y un WS echo (wss://echo.websocket.events).

Contexto

Apps C++ que consumen APIs internas (registry_api, deploy_server) suelen requerir scripts curl/Postman aparte para debugging. Tener un inspector embebido reduce friccion.

Arquitectura

cpp/
├── vendor/cpp-httplib/
│   └── httplib.h                # NEW (header-only, MIT)
├── functions/core/
│   ├── http_inspector.h/.cpp/.md  # NEW (impure component)
│   └── websocket_client.h/.cpp/.md  # NEW (impure component)
└── apps/primitives_gallery/
    ├── demos_net.cpp            # NEW
    ├── demos.h                  # MOD
    ├── main.cpp                 # MOD
    └── CMakeLists.txt           # MOD
cpp/CMakeLists.txt               # MOD

API propuesta

namespace fn {

struct HttpHeader { std::string key, value; };
struct HttpInspectorState {
    std::string url    = "https://httpbin.org/get";
    std::string method = "GET";
    std::vector<HttpHeader> headers;
    std::string body;
    int                     last_status = 0;
    std::vector<HttpHeader> last_headers;
    std::string             last_body;
    double                  last_ms = 0.0;
    bool                    in_flight = false;  // request en background
    std::string             error;
};
void http_inspector(const char* id, HttpInspectorState&, ImVec2 size = {-1, -1});

struct WsMessage { double t; bool incoming; std::string text; };
struct WebSocketClientState {
    std::string url = "wss://echo.websocket.events";
    bool        connected = false;
    std::string send_buf;
    std::vector<WsMessage> messages;   // capped at 500
    float       rate_msgs_s = 0.f;
    std::string error;
};
void websocket_client(const char* id, WebSocketClientState&, ImVec2 size = {-1, -1});
}

Tareas

Fase 1 — Vendor + decision WS

  • 1.1 Vendorear httplib.h (pinear version reciente con TLS opcional).
  • 1.2 Decidir cliente WS:
    • Opcion A: cpp-httplib WebSocketClient si la version vendoreada lo trae.
    • Opcion B: vendorear websocketpp (header-only-ish, depende de Asio header-only).
  • 1.3 Documentar la decision en cpp/vendor/<lib>/README.md.

Fase 2 — http_inspector

  • 2.1 Implementar el componente. Request en background con std::thread (ver process_runner_cpp_core como patrón).
  • 2.2 Pretty-print: si Content-Type: application/json, formatear con un mini parser/printer JSON (o copiar uno minimal; no necesitamos validacion exhaustiva).
  • 2.3 .md con frontmatter (kind: component, purity: impure, error_type).

Fase 3 — websocket_client

  • 3.1 Implementar connect/disconnect en thread; lockear cola de mensajes con mutex; copiar a state.messages en websocket_client() (main thread).
  • 3.2 Calcular rate_msgs_s como contador por segundo con ventana deslizante (puede usar time_series_buffer_cpp_core).
  • 3.3 .md.
  • 4.1 demos_net.cpp con demo_http_inspector() y demo_websocket_client().
  • 4.2 Registrar.

Fase 5 — Tests + docs

  • 5.1 Test pretty-print JSON sobre payload conocido.
  • 5.2 Test ratelimit del rate_msgs_s.
  • 5.3 Smoke test (opcional, requires net): GET a 127.0.0.1 contra un servidor levantado en el test.
  • 5.4 ./fn index + ./fn show.

Ejemplo de uso

fn::HttpInspectorState http;
fn::WebSocketClientState ws;

fn::run_app("net", [&]{
    if (ImGui::BeginTabBar("net")) {
        if (ImGui::BeginTabItem("HTTP")) { fn::http_inspector("##h", http); ImGui::EndTabItem(); }
        if (ImGui::BeginTabItem("WS"))   { fn::websocket_client("##w", ws); ImGui::EndTabItem(); }
        ImGui::EndTabBar();
    }
});

Decisiones de diseño

  • cpp-httplib vs libcurl: header-only gana en complejidad de build. TLS via OpenSSL si esta disponible; degradar a HTTP si no.
  • Mensajes WS capped: 500 maximo en buffer para no crecer indefinidamente; descartar oldest.
  • Sin authentication helpers: el header Authorization se mete a mano. UX simple.

Riesgos

  • TLS: cpp-httplib requiere OpenSSL para https://. Documentar en CMake como opt-in.
  • WS reconnect: no implementar auto-reconnect en MVP. El usuario reconecta manualmente.
  • Threading: cuidado con marshalling de strings entre thread y UI. Mutex obligatorio en mensajes.