# 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<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`.

### 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.
