aissia/plans/webmodule-implementation.md
StillHammer 18f4f16213 feat: Add WebModule for HTTP requests via IIO
Implements WebModule that allows other modules to make HTTP requests
through IIO pub/sub messaging system.

Features:
- HTTP GET/POST support via existing HttpClient
- Request/response via IIO topics (web:request/web:response)
- Security: blocks localhost and private IPs
- Statistics tracking (total, success, failed)
- Hot-reload state preservation
- Custom headers and timeout configuration

Module architecture:
- WebModule.h/cpp: 296 lines total (within 300 line limit)
- config/web.json: Configuration file
- 10 integration tests (TI_WEB_001 to TI_WEB_010)

Tests: 120/120 passing (110 existing + 10 new)

Protocol:
- Subscribe: web:request
- Publish: web:response
- Request fields: requestId, url, method, headers, body, timeoutMs
- Response fields: requestId, success, statusCode, body, error, durationMs

đŸ€– Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 17:15:46 +08:00

12 KiB

Plan d'Implémentation: WebModule

Objectif: Ajouter un module hot-reload permettant aux autres modules de faire des requĂȘtes HTTP de maniĂšre dynamique via IIO.

Status: 📋 PlanifiĂ© PrioritĂ©: Moyenne DurĂ©e estimĂ©e: 2-3h


1. Vue d'Ensemble

Architecture

┌─────────────────────────────────────────────────┐
│         Modules Clients                          │
│  (AI, Monitoring, Scheduler, etc.)               │
│                                                  │
│  → Publient: "web:request"                       │
│  ← Reçoivent: "web:response"                     │
└──────────────┬──────────────────────────────────┘
               │ IIO pub/sub
               ▌
┌─────────────────────────────────────────────────┐
│           WebModule (Hot-reload)                 │
│                                                  │
│  ‱ Subscribe: "web:request"                      │
│  ‱ Execute HTTP via HttpClient.hpp               │
│  ‱ Publish: "web:response"                       │
│  ‱ Track stats (total, success, failed)          │
│  ‱ State preservation (hot-reload)               │
└──────────────┬──────────────────────────────────┘
               │ Uses existing HttpClient.hpp
               ▌
           Internet

Avantages

✅ Hot-reload: Rechargement sans arrĂȘter le systĂšme ✅ DĂ©couplage: Modules clients ignorent les dĂ©tails HTTP ✅ CentralisĂ©: Un seul point pour toutes les requĂȘtes HTTP ✅ Statistiques: Tracking automatique (total, succĂšs, Ă©checs) ✅ État persistant: Stats survivent au hot-reload ✅ RĂ©utilisation: Utilise HttpClient.hpp existant


2. Fichiers à Créer

2.1 Module Core

src/modules/WebModule.h (70 lignes)

#pragma once
#include <grove/IModule.h>
#include <memory>
#include <spdlog/spdlog.h>

namespace aissia {

class WebModule : public grove::IModule {
public:
    WebModule();
    ~WebModule() override = default;

    // IModule interface
    void setConfiguration(const grove::IDataNode& config,
                         grove::IIO* io,
                         grove::ITaskScheduler* scheduler) override;
    const grove::IDataNode& getConfiguration() override;
    void process(const grove::IDataNode& input) override;
    std::unique_ptr<grove::IDataNode> getHealthStatus() override;
    void shutdown() override;

    // State management (hot-reload)
    std::unique_ptr<grove::IDataNode> getState() override;
    void setState(const grove::IDataNode& state) override;

private:
    void processMessages();
    void handleWebRequest(const grove::IDataNode& request);

    grove::IIO* m_io = nullptr;
    std::shared_ptr<spdlog::logger> m_logger;
    std::unique_ptr<grove::IDataNode> m_config;

    // Configuration
    int m_requestTimeoutMs = 30000;
    int m_maxConcurrentRequests = 10;

    // Statistics
    int m_totalRequests = 0;
    int m_successfulRequests = 0;
    int m_failedRequests = 0;
};

} // namespace aissia

src/modules/WebModule.cpp (180 lignes)

  • ImplĂ©mentation complĂšte
  • Gestion GET/POST
  • Gestion des erreurs
  • Publication des rĂ©ponses
  • État pour hot-reload

2.2 Configuration

config/web.json (nouveau)

{
    "enabled": true,
    "requestTimeoutMs": 30000,
    "maxConcurrentRequests": 10,
    "allowedDomains": [
        "api.example.com",
        "*.openai.com"
    ],
    "blockedDomains": []
}

2.3 Tests

tests/modules/WebModuleTests.cpp (10 tests)

TI_WEB_001: Simple GET Request
TI_WEB_002: POST Request with Body
TI_WEB_003: Invalid URL Handling
TI_WEB_004: Timeout Handling
TI_WEB_005: Multiple Concurrent Requests
TI_WEB_006: Request ID Tracking
TI_WEB_007: Statistics Tracking
TI_WEB_008: State Serialization
TI_WEB_009: Configuration Loading
TI_WEB_010: Error Response Format

3. Protocole IIO

3.1 RequĂȘte (web:request)

Topic: web:request

Payload:

{
    "requestId": "unique-id-123",
    "url": "https://api.example.com/data",
    "method": "GET",
    "headers": {
        "Authorization": "Bearer xxx",
        "Content-Type": "application/json"
    },
    "body": "{\"key\": \"value\"}",
    "timeoutMs": 5000
}

Champs:

  • requestId (string, required): ID unique pour matcher la rĂ©ponse
  • url (string, required): URL complĂšte avec schĂ©ma
  • method (string, optional): "GET", "POST", "PUT", "DELETE" (default: "GET")
  • headers (object, optional): Headers HTTP custom
  • body (string, optional): Body pour POST/PUT
  • timeoutMs (int, optional): Timeout custom (default: 30000)

3.2 Réponse (web:response)

Topic: web:response

Payload (Success):

{
    "requestId": "unique-id-123",
    "success": true,
    "statusCode": 200,
    "body": "{\"result\": \"data\"}",
    "headers": {
        "Content-Type": "application/json"
    },
    "durationMs": 234
}

Payload (Error):

{
    "requestId": "unique-id-123",
    "success": false,
    "error": "Connection timeout",
    "errorCode": "TIMEOUT",
    "durationMs": 30001
}

4. Étapes d'ImplĂ©mentation

Phase 1: Core Module (1h)

  1. Créer les fichiers de base

    • src/modules/WebModule.h
    • src/modules/WebModule.cpp
    • config/web.json
  2. Implémenter les méthodes IModule

    • setConfiguration() - Subscribe "web:request"
    • process() - Appeler processMessages()
    • getHealthStatus() - Retourner stats
    • shutdown() - Log final
    • getState() / setState() - SĂ©rialisation stats
  3. Implémenter handleWebRequest()

    • Extraction des paramĂštres
    • Validation URL
    • Appel HttpClient (GET/POST)
    • Gestion erreurs (try/catch)
    • Publication "web:response"
  4. Ajouter au CMakeLists.txt

    add_library(WebModule SHARED
        src/modules/WebModule.cpp
    )
    target_link_libraries(WebModule PRIVATE grove_impl)
    
  5. Ajouter au main.cpp

    // Load WebModule
    moduleConfigs.push_back({
        "WebModule",
        "./build/modules/libWebModule.so",
        "./config/web.json"
    });
    

Phase 2: Tests (1h)

  1. Créer les tests

    • tests/modules/WebModuleTests.cpp
    • Mock HTTP server (simple echo server)
    • 10 tests unitaires
    • IntĂ©gration avec MockIO
  2. Exécuter les tests

    cmake --build build --target aissia_tests
    ./build/tests/aissia_tests "[web]"
    

Phase 3: Documentation & Exemples (30min)

  1. Documenter l'utilisation

    • Ajouter exemple dans docs/modules/WebModule.md
    • Mettre Ă  jour CLAUDE.md
    • Mettre Ă  jour README.md
  2. Créer un exemple d'utilisation

    • Exemple dans AIModule ou nouveau module

5. Exemple d'Utilisation

Dans un module client (ex: AIModule)

// 1. Dans setConfiguration() - S'abonner aux réponses
if (m_io) {
    grove::SubscriptionConfig subConfig;
    m_io->subscribe("web:response", subConfig);
}

// 2. Faire une requĂȘte HTTP
void AIModule::fetchExternalData() {
    auto request = std::make_unique<grove::JsonDataNode>("request");
    request->setString("requestId", "weather-" + std::to_string(m_requestCounter++));
    request->setString("url", "https://api.weather.com/current");
    request->setString("method", "GET");

    // Optional headers
    auto headers = std::make_unique<grove::JsonDataNode>("headers");
    headers->setString("Authorization", "Bearer " + m_apiKey);
    request->setChild("headers", std::move(headers));

    m_io->publish("web:request", std::move(request));
}

// 3. Dans processMessages() - Recevoir la réponse
if (msg.topic == "web:response" && msg.data) {
    std::string requestId = msg.data->getString("requestId", "");

    if (requestId.find("weather-") == 0) {
        bool success = msg.data->getBool("success", false);

        if (success) {
            std::string body = msg.data->getString("body", "");
            int statusCode = msg.data->getInt("statusCode", 0);

            m_logger->info("Weather data received: {} bytes", body.size());
            // Parse JSON and use data
        } else {
            std::string error = msg.data->getString("error", "Unknown");
            m_logger->error("Weather request failed: {}", error);
        }
    }
}

6. Sécurité & Limitations

Sécurité

  1. Validation URL

    • VĂ©rifier schĂ©ma (https:// recommandĂ©)
    • Whitelist/Blacklist de domaines (config)
    • Pas d'exĂ©cution de code arbitraire
  2. Rate Limiting

    • Max concurrent requests (config)
    • Timeout par dĂ©faut (30s)
    • Pas de retry automatique (responsabilitĂ© du client)
  3. Sanitization

    • Headers validĂ©s
    • Pas d'injection possible

Limitations

  • Pas de streaming: RequĂȘtes one-shot uniquement
  • Pas de websockets: HTTP classique seulement
  • Pas de retry: Le client doit gĂ©rer
  • Pas de cache: Chaque requĂȘte est exĂ©cutĂ©e
  • Thread-safe: Mais pas de parallĂ©lisation interne

7. Extensions Futures (Optionnel)

Phase 4: Features Avancées

  • Cache HTTP: LRU cache pour rĂ©ponses GET
  • Retry automatique: Avec backoff exponentiel
  • Circuit breaker: Protection contre services down
  • MĂ©triques avancĂ©es: Latence P50/P95/P99
  • Support HTTPS custom: Certificats custom
  • Compression: gzip/deflate support
  • Streaming: Support chunked transfer

Phase 5: Tools pour l'Agent LLM

  • Ajouter fetch_url tool dans InternalTools
  • Agent peut faire "Fetch https://example.com"
  • Parsing HTML automatique (option)

8. CritĂšres de SuccĂšs

Fonctionnel

  • Module compile et charge sans erreur
  • GET requests fonctionnent
  • POST requests fonctionnent
  • Erreurs sont gĂ©rĂ©es correctement
  • Stats sont trackĂ©es
  • Hot-reload prĂ©serve l'Ă©tat

Tests

  • 10/10 tests passent
  • Coverage > 80%
  • Pas de memory leaks (valgrind)

Documentation

  • README.md updated
  • Exemples d'utilisation fournis
  • Protocol IIO documentĂ©

Performance

  • Latency < 100ms overhead (vs direct HTTP)
  • Pas de blocking de la main loop
  • Memory footprint < 1MB

9. Checklist de Validation

Avant de merger:

  • Code review (self-review)
  • Tests unitaires passent
  • Tests d'intĂ©gration passent
  • Documentation Ă  jour
  • Pas de warnings de compilation
  • Module hot-reload testĂ© manuellement
  • Config JSON validĂ©
  • Exemple fonctionnel créé
  • Commit message descriptif
  • Branch mergĂ©e vers master

10. Fichiers Affectés

Nouveaux fichiers

src/modules/WebModule.h
src/modules/WebModule.cpp
config/web.json
tests/modules/WebModuleTests.cpp
plans/webmodule-implementation.md (ce fichier)

Fichiers modifiés

CMakeLists.txt                  # Ajouter WebModule target
src/main.cpp                    # Charger WebModule
README.md                       # Documentation
CLAUDE.md                       # RÚgles de développement

Fichiers utilisés (existants)

src/shared/http/HttpClient.hpp  # Réutilisé pour HTTP
external/GroveEngine/           # IModule, IIO, etc.

Notes Techniques

Dépendances

  • ✅ HttpClient.hpp (dĂ©jĂ  implĂ©mentĂ©)
  • ✅ GroveEngine (IModule, IIO)
  • ✅ nlohmann/json (parsing)
  • ✅ spdlog (logging)

Compatibilité

  • ✅ Windows (HTTPS via WinHTTP)
  • ✅ Linux/WSL (HTTPS via libcurl si disponible)
  • ✅ Hot-reload ready

Performance

  • RequĂȘtes asynchrones dans le sens oĂč elles ne bloquent pas la main loop
  • Mais chaque requĂȘte est synchrone (HttpClient bloque jusqu'Ă  rĂ©ponse)
  • Pour async vrai, il faudrait un thread pool (Phase 4+)

Auteur: Claude Code Date: 2025-11-28 Version: 1.0