--- id: "0033" title: "C++ http_inspector + websocket_client" status: pendiente type: feature domain: - cpp-stack scope: multi-app priority: baja depends: [] blocks: [] related: [] created: 2026-05-17 updated: 2026-05-17 tags: [] --- # 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](https://github.com/yhirose/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](https://github.com/zaphoyd/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 ```cpp namespace fn { struct HttpHeader { std::string key, value; }; struct HttpInspectorState { std::string url = "https://httpbin.org/get"; std::string method = "GET"; std::vector headers; std::string body; int last_status = 0; std::vector 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 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//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`. ### Fase 4 — Gallery demo - 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 ```cpp 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.