LLMApi-:-OpenAPI Dynamischer Mock-Generator - :-Lade jedes Spec.,-Mocke jede API (Deutsch (German))

LLMApi-:-OpenAPI Dynamischer Mock-Generator - :-Lade jedes Spec.,-Mocke jede API

Wednesday, 05 November 2025

//

14 minute read

ANMERKUNG: Dieser Artikel ist in erster Linie AI als Teil meines Nuget-Pakets als Release-Dokumentation erzeugt.Es ist ziemlich interessant, also habe ich es hier gesetzt, aber wenn das ein Problem für Sie ist, ignorieren Sie es bitte.

Einleitung

Haben Sie jemals benötigt, um gegen eine API zu testen, die noch nicht fertig war ,? , oder wollte offline ohne Schlagen der Geschwindigkeit Grenzen entwickeln , ? , Der OpenAPI Dynamic Mock Generator können Sie jede OpenAPI-Spezifikation laden und erstellt sofort eine voll funktionsfähige Mock-API mit realistischen ., , LLM , M- , generiert Daten , . ,

Keine Konfigurationsdateien - .-Keine manuelle Endpoint-Erstellung -.- Zeigen Sie es einfach auf eine OpenAPI-Spezifikation und starten Sie Anfragen -MSC2-

NuGet NuGet

Sie können die GitHub hier für das Projekt – alle öffentlichen Bereiche usw. –

OpenApi-Manager

Das Problem: API Abhängigkeiten Block-Entwicklung

Moderne Anwendungen hängen von Dutzenden von externen APIs ab.

graph TD
    A[Your App] --> B{External API}
    B -->|Not Ready| C[Development Blocked]
    B -->|Rate Limited| D[Can't Test Freely]
    B -->|Requires Auth| E[Complex Setup]
    B -->|Expensive| F[Cost Concerns]
    B -->|Unreliable| G[Flaky Tests]

Traditionelle Lösungen beinhalten

  • Manuelles Schreiben von Mock-Antworten
  • Recording-/-Replaying HTTP-Traffic (-Bruttle-MSC2- schwer zu pflegen
  • Verwendung von hardcodierten Vorrichtungen

Die Lösung: Dynamisches OpenAPI-Mocking

Zeigen Sie das System auf jede OpenAPI spece.,, und es automatisch.

  1. Parses die Spezifikation
  2. Entdeckt alle Endpunkte
  3. Erzeugt realistische Mock-Daten mit einem LLM
  4. Serviert die Mock API auf Ihrem lokalen Rechner
sequenceDiagram
    participant Dev as Developer
    participant System as Mock System
    participant Spec as OpenAPI Spec
    participant LLM as Local LLM

    Dev->>System: Load spec from URL/file
    System->>Spec: Parse OpenAPI document
    Spec-->>System: Endpoints, schemas, descriptions
    System->>System: Register dynamic routes

    Dev->>System: GET /petstore/pet/123
    System->>LLM: Generate data for "Pet" schema
    LLM-->>System: Realistic pet data
    System-->>Dev: {"id": 123, "name": "Max", ...}

Wie es funktioniert

Architektur im Überblick

Das OpenAPI-System besteht aus mehreren aufeinander abgestimmten Komponenten

graph TB
    A[HTTP Request] --> B{Route Matches?}
    B -->|No| C[404 Not Found]
    B -->|Yes| D[DynamicOpenApiManager]
    D --> E[Find Matching Endpoint]
    E --> F[OpenApiRequestHandler]
    F --> G[Extract Schema from Spec]
    G --> H[Build LLM Prompt]
    H --> I[PromptBuilder]
    I --> J[Include Context?]
    J -->|Yes| K[OpenApiContextManager]
    J -->|No| L[LLM Client]
    K --> L
    L --> M[Get Response]
    M --> N[JsonExtractor]
    N --> O[Return Mock Data]

Schlüsselkomponenten

  1. DynamicOpenApiManager Verwaltet geladene Spezifikationen und Routenabgleich
  2. OpenApiSpecLoader Dokumente und Parsen von OpenAPI
  3. OpenApiRequestHandler Erzeugt Antworten für abgestimmte Endpunkte
  4. PromptBuilder Erstellen von LLM-Prompten aus OpenAPI-Schemas
  5. OpenApiContextManager Bewahrt die Konsistenz über Anrufe hinweg.

Belastungsangaben

Technische Daten können aus drei Quellen geladen werden

Fern-URL

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "petstore",
  "source": "https://petstore3.swagger.io/api/v3/openapi.json",
  "basePath": "/petstore"
}

Lokale Datei

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "my-api",
  "source": "./specs/my-api.yaml",
  "basePath": "/api/v1"
}

Daten-URL zur Verarbeitung von (Basis-64

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "inline-api",
  "source": "data:application/json;base64,eyJvcGVuYXBpIjoiMy...",
  "basePath": "/api"
}

Spec-Lastvorgang

Hier ist das, was passiert, wenn Sie eine Spezifität laden.

public async Task<SpecLoadResult> LoadSpecAsync(
    string name,
    string source,
    string? basePath = null,
    string? contextName = null)
{
    // 1. Use scoped service factory for OpenApiSpecLoader
    using var scope = _scopeFactory.CreateScope();
    var specLoader = scope.ServiceProvider
        .GetRequiredService<OpenApiSpecLoader>();

    // 2. Load the OpenAPI document
    var document = await specLoader.LoadSpecAsync(source);

    // 3. Determine base path from spec or parameter
    var effectiveBasePath = basePath
        ?? document.Servers?.FirstOrDefault()?.Url
        ?? "/api";

    // 4. Store spec with configuration
    var config = new OpenApiSpecConfig
    {
        Name = name,
        Source = source,
        Document = document,
        BasePath = effectiveBasePath,
        ContextName = contextName,
        LoadedAt = DateTimeOffset.UtcNow
    };

    _specs.AddOrUpdate(name, config, (_, __) => config);

    // 5. Notify listeners via SignalR
    await NotifySpecLoaded(name, effectiveBasePath);

    return new SpecLoadResult
    {
        Name = name,
        BasePath = effectiveBasePath,
        EndpointCount = CountEndpoints(document),
        Success = true
    };
}

Dynamische Route passend

Wenn eine Anfrage eintrifft, stimmt das System mit allen geladenen Specs überein.

public OpenApiEndpointMatch? FindMatchingEndpoint(string path, string method)
{
    // Try each loaded spec
    foreach (var spec in _specs.Values)
    {
        // Remove base path prefix
        var relativePath = path;
        if (path.StartsWith(spec.BasePath))
        {
            relativePath = path.Substring(spec.BasePath.Length);
        }

        // Find matching path in OpenAPI document
        var (pathTemplate, operation) = FindOperation(
            spec.Document,
            relativePath,
            method);

        if (operation != null)
        {
            return new OpenApiEndpointMatch
            {
                Spec = spec,
                PathTemplate = pathTemplate,
                Operation = operation,
                Method = ParseMethod(method)
            };
        }
    }

    return null;
}

Bearbeitung der Anfrage

Sobald ein übereinstimmender Endpunkt gefunden wurde, erzeugt der Handler eine Antwort.

public async Task<string> HandleRequestAsync(
    HttpContext context,
    OpenApiDocument document,
    string path,
    OperationType method,
    OpenApiOperation operation,
    string? contextName = null,
    CancellationToken cancellationToken = default)
{
    // 1. Extract request body
    var requestBody = await ReadRequestBodyAsync(context.Request);

    // 2. Get success response schema
    var shape = ExtractResponseSchema(operation);

    // 3. Get context history if using contexts
    var contextHistory = !string.IsNullOrWhiteSpace(contextName)
        ? _contextManager.GetContextForPrompt(contextName)
        : null;

    // 4. Build prompt from OpenAPI metadata
    var description = operation.Summary ?? operation.Description;
    var prompt = _promptBuilder.BuildPrompt(
        method.ToString(),
        path,
        requestBody,
        new ShapeInfo { Shape = shape },
        streaming: false,
        description: description,
        contextHistory: contextHistory);

    // 5. Get response from LLM
    var rawResponse = await _llmClient.GetCompletionAsync(
        prompt,
        cancellationToken);

    // 6. Extract clean JSON
    var jsonResponse = JsonExtractor.ExtractJson(rawResponse);

    // 7. Store in context if configured
    if (!string.IsNullOrWhiteSpace(contextName))
    {
        _contextManager.AddToContext(
            contextName,
            method.ToString(),
            path,
            requestBody,
            jsonResponse);
    }

    return jsonResponse;
}

Schemaextraktion

Das System extrahiert Antwortschemata aus OpenAPI-Definitionen

private string? ExtractResponseSchema(OpenApiOperation operation)
{
    // Look for successful response (2xx)
    var successResponse = operation.Responses
        .FirstOrDefault(r => r.Key.StartsWith("2"))
        .Value;

    if (successResponse == null)
        return null;

    // Get JSON content
    var jsonContent = successResponse.Content
        .FirstOrDefault(c => c.Key.Contains("json"))
        .Value;

    if (jsonContent?.Schema == null)
        return null;

    // Convert OpenAPI schema to JSON Schema
    return ConvertToJsonSchema(jsonContent.Schema);
}

private string ConvertToJsonSchema(OpenApiSchema schema)
{
    // Recursively build JSON Schema representation
    var builder = new StringBuilder();
    builder.Append("{");

    if (schema.Type != null)
    {
        builder.Append($"\"type\":\"{schema.Type}\"");
    }

    if (schema.Properties?.Count > 0)
    {
        builder.Append(",\"properties\":{");
        var props = schema.Properties
            .Select(p => $"\"{p.Key}\":{ConvertToJsonSchema(p.Value)}");
        builder.Append(string.Join(",", props));
        builder.Append("}");
    }

    if (schema.Items != null)
    {
        builder.Append(",\"items\":");
        builder.Append(ConvertToJsonSchema(schema.Items));
    }

    builder.Append("}");
    return builder.ToString();
}

Reale Verwendung von -

Beispiel: API für Petstore

Lassen Sie uns gehen durch die Spott der klassischen Petstore API-Publikum

Schritt - Laden Sie das Spec

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "petstore",
  "source": "https://petstore3.swagger.io/api/v3/openapi.json",
  "basePath": "/petstore"
}

Ansprechrate

{
  "name": "petstore",
  "basePath": "/petstore",
  "endpointCount": 19,
  "endpoints": [
    {"path": "/petstore/pet", "method": "POST"},
    {"path": "/petstore/pet/{petId}", "method": "GET"},
    {"path": "/petstore/pet/findByStatus", "method": "GET"},
    ...
  ],
  "success": true
}

Schritt Die Mock-Endpunkte verwenden

Jetzt sind alle Endpunkte verfügbar.

### Get a pet by ID
GET /petstore/pet/123

### Response (auto-generated):
{
  "id": 123,
  "name": "Max",
  "category": {
    "id": 1,
    "name": "Dogs"
  },
  "photoUrls": [
    "https://example.com/max1.jpg"
  ],
  "tags": [
    {"id": 1, "name": "friendly"},
    {"id": 2, "name": "trained"}
  ],
  "status": "available"
}
### Find pets by status
GET /petstore/pet/findByStatus?status=available

### Response (auto-generated array):
[
  {
    "id": 42,
    "name": "Buddy",
    "status": "available",
    ...
  },
  {
    "id": 43,
    "name": "Luna",
    "status": "available",
    ...
  }
]

Schritt Besichtigen Sie das Spec

GET /api/openapi/specs/petstore

### Shows full details:
### - All endpoints
### - Load time
### - Context configuration
### - Base path

Schritt »4:« Nachladen, wenn sich das Spezifik ändert

POST /api/openapi/specs/petstore/reload

Schritt Entfernen, wenn erledigt

DELETE /api/openapi/specs/petstore

Mehrere Specs gleichzeitig

Sie können mehrere Spezifikationen auf einmal laden.

### Load Petstore at /petstore
POST /api/openapi/specs
{"name": "petstore", "source": "...", "basePath": "/petstore"}

### Load GitHub API at /github
POST /api/openapi/specs
{"name": "github", "source": "...", "basePath": "/github"}

### Load Stripe API at /stripe
POST /api/openapi/specs
{"name": "stripe", "source": "...", "basePath": "/stripe"}

### All three APIs now available simultaneously:
GET /petstore/pet/123
GET /github/users/octocat
GET /stripe/customers/cus_123

Spezifikationen mit Kontexten

Für noch mehr Realismus, einen Kontext einem Spec.: zuweisen

POST /api/openapi/specs
Content-Type: application/json

{
  "name": "petstore",
  "source": "https://petstore3.swagger.io/api/v3/openapi.json",
  "basePath": "/petstore",
  "contextName": "petstore-session"
}

Jetzt teilen sich alle Petstore-Endpunkte den gleichen Kontext.

### Create a pet
POST /petstore/pet
{"name": "Max", "status": "available"}

### Response: {"id": 42, "name": "Max", "status": "available"}

### Get the pet (will reference same ID and name)
GET /petstore/pet/42

### Response: {"id": 42, "name": "Max", "status": "available"}
### Notice: Consistent ID and name from context

Testendpunkt

Mit dem Testendpunkt können Sie einen Endpunkt ausprobieren, ohne eine echte Anfrage zu stellen.

POST /api/openapi/test
Content-Type: application/json

{
  "specName": "petstore",
  "path": "/pet/123",
  "method": "GET"
}

### Returns mock response without affecting routes

Dies ist nützlich für die

  • Vorschau der Antworten vor der Integration
  • Prüfung spezifischer Endpunkte in Isolation
  • Probleme mit dem Debugging-Schema

Verwaltungsoberfläche

Für visuelles Management-Besuchen http://localhost:5116/OpenApi:

graph TD
    A[OpenAPI Manager UI] --> B[Load Spec Section]
    A --> C[Spec List]
    A --> D[Context Viewer]

    B --> E[URL Input]
    B --> F[JSON Input]
    B --> G[Context Configuration]

    C --> H[Spec Card]
    H --> I[Reload Button]
    H --> J[Delete Button]
    H --> K[View Endpoints]

    D --> L[Active Contexts]
    L --> M[Context Details]
    L --> N[Clear Context]

Merkmale

  • Ziehen Sie - und - Datei hochladen
  • Entdeckung des Live-Endpunkts Alle Endpunkte sofort sehen
  • Eins---Klick testen Testen Sie jeden Endpunkt mit einem Knopf
  • Echtzeit-Meldungen SignalR aktualisiert, wenn Spezifikationen laden
  • Syntax Hervorhebung Schöne JSON-Antwortanzeige
  • Kontextverwaltung Ansicht und klare Kontexte

Erweiterte Funktionen

Pfadparameter

Pfadparameter werden automatisch extrahiert

# OpenAPI Spec
/pet/{petId}:
  get:
    parameters:
      - name: petId
        in: path
        schema:
          type: integer
GET /petstore/pet/123
### LLM receives: "Generate data for Pet with petId=123"
### Response: {"id": 123, ...}

Abfrageparameter

Abfrageparameter beeinflussen die Antwort

/pet/findByStatus:
  get:
    parameters:
      - name: status
        in: query
        schema:
          type: string
          enum: [available, pending, sold]
GET /petstore/pet/findByStatus?status=available
### LLM receives: "Generate array of Pets with status=available"
### Response: [{"status": "available", ...}, ...]

Antragstellen

POST-/-PUT Körper sind in der Eingabeaufforderung enthalten.

/pet:
  post:
    requestBody:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Pet'
POST /petstore/pet
Content-Type: application/json

{"name": "Max", "status": "available"}

### LLM receives: "Generate response for creating Pet with name=Max, status=available"
### Response: {"id": 42, "name": "Max", "status": "available"}

Beschreibungen und Zusammenfassungen

OpenAPI Beschreibungen führen das LLM-:.

/pet/{petId}:
  get:
    summary: Find pet by ID
    description: Returns a single pet based on the ID provided

Diese sind in der Eingabeaufforderung enthalten, die dem LLM hilft, den Endpunkt zu verstehen.

Codes für den Antwortstatus

Das System verwendet die erste erfolgreiche Antwort

responses:
  '200':
    description: Successful operation
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Pet'
  '404':
    description: Pet not found

Nur das Schema der Mock-Generierung wird zur Zeit nicht simuliert.

SignalR Real---Zeitaktualisierung

Wenn Spezifikationen geladen werden, erhält die UI Echtzeit-Benachrichtigungen über SignalR.:.

public async Task NotifySpecLoaded(string name, string basePath)
{
    await _hubContext.Clients.All.SendAsync("SpecLoaded", new
    {
        name,
        basePath,
        timestamp = DateTimeOffset.UtcNow
    });
}

public async Task NotifySpecDeleted(string name)
{
    await _hubContext.Clients.All.SendAsync("SpecDeleted", new
    {
        name,
        timestamp = DateTimeOffset.UtcNow
    });
}

UI-Code für die JavaScript-Benutzeroberfläche

const connection = new signalR.HubConnectionBuilder()
    .withUrl('/hubs/openapi')
    .build();

connection.on('SpecLoaded', (data) => {
    showNotification(`Spec "${data.name}" loaded at ${data.basePath}`, 'success');
    refreshSpecList();
});

connection.on('SpecDeleted', (data) => {
    showNotification(`Spec "${data.name}" deleted`, 'info');
    refreshSpecList();
});

Format-Unterstützung

Das System unterstützt:

  • Öffnen Sie die API-Datei
  • Öffnen Sie die API-Datei
  • Swagger - 2.0-
  • JSON-Format
  • YAML-Format

Sowohl JSON als auch YAML-Spezifikationen werden automatisch erkannt und analysiert.

Best Practices

Beschreibende Spec-Namen verwenden

 Bad:  {"name": "spec1", ...}
 Good: {"name": "github-v3", ...}

Bestimmen Sie geeignete Basispfade

Konflikte vermeiden, indem Sie einzigartige Basispfade verwenden

### Good separation
/petstore/...
/github/...
/stripe/...

### Bad (conflicts!)
/api/... (multiple specs)

Umladen, wenn sich die Daten ändern

Wenn Ihre OpenAPI-Spezifikation aktualisiert wird, laden Sie es neu.

POST /api/openapi/specs/my-api/reload

Verwendung von Kontexten für verwandte Anrufe

POST /api/openapi/specs
{
  "name": "petstore",
  "source": "...",
  "contextName": "test-session"
}

### Now all petstore calls maintain consistency

Bereinigen Sie nach der Prüfung

Entfernen Sie die Spezifika you-'-re nicht mehr verwenden

DELETE /api/openapi/specs/old-spec

Einschränkungen

  1. Codes für den Antwortstatus Nur erfolgreiche Antworten werden verspottet
  2. Authentifizierung Auth Header werden akzeptiert, aber nicht validiert.
  3. Validierung Beantragung einer Validierung gegen Schemas wird nicht durchgesetzt
  4. Mitgliedstaat Keine aktuelle Datenbank Es werden jedes Mal neue Daten erzeugt, es sei denn mit Kontexten
  5. Leistung Die LLM-Generation fügt Latenzwerte pro Anfrage hinzu

Integration mit regelmäßigen Mock-Endpunkten

OpenAPI-Spezifikationen funktionieren neben regelmäßigen /api/mock Endpunkte

### OpenAPI-based (from spec)
GET /petstore/pet/123
### Uses Pet schema from OpenAPI spec

### Regular mock (shape-based)
GET /api/mock/custom?shape={"id":0,"name":"string"}
### Uses explicit shape parameter

Beide verwenden das gleiche zugrunde liegende LLM, unterscheiden sich aber in der Art und Weise, wie das Schema zur Verfügung gestellt wird.

Leistungsoptimierung

Caching

Geladene Spezifikationen werden im Speicher zwischengespeichert.

private readonly ConcurrentDictionary<string, OpenApiSpecConfig> _specs = new();

Dienstlebensdauer

DynamicOpenApiManager ist ein Singleton, also bleiben die Spezifikationen für die Lebensdauer der Anwendung geladen.

Parallele Spec-Ladung

Mehrere Spezifikationen können parallel geladen werden

### Send these simultaneously
POST /api/openapi/specs {"name": "spec1", ...}
POST /api/openapi/specs {"name": "spec2", ...}
POST /api/openapi/specs {"name": "spec3", ...}

Alle drei werden parallel geladen, nicht sequenziell.

Fehlerbehebung

Spec Won-'-t-Last

Problemstellung Spec-Ladung fehlgeschlagen

Lösungen

  • Überprüfen Sie die URL ist zugänglich
  • Überprüfen Sie, ob die Datei für lokale Pfade existiert.
  • Stellen Sie sicher, dass der JSON-/-YAML gültig ist
  • Suchen Sie nach CORS-Problemen für entfernte URLs

Endpunkt nicht gefunden

Problemstellung -404-Wert des erwarteten Endpunkts

Lösungen

  • Überprüfen Sie den Basispfad. /petstore + /pet/123 = /petstore/pet/123
  • Prüfen Sie die Spezifikation definiert diesen Pfad
  • Stellen Sie sicher, dass die HTTP-Methode mit der POST-Methode übereinstimmt.

Die Reaktion bewirkt eine Übereinstimmung mit Schema

Problemstellung Generierte Daten entsprechen dem erwarteten Schema

Lösungen

  • Prüfen Sie, ob das Schema in der Spezifikation korrekt ist
  • Verifizieren Sie sich mit der richtigen Antwort
  • Erinnere dich an die Generation der LLM ist probabilistisch, nicht deterministisch

Schlußfolgerung

Der OpenAPI Dynamic Mock Generator verwandelt jede OpenAPI-Spezifikation in eine vollwertige --Funktions-Mock API in Sekunden...Keine manuelle Konfiguration.

Laden Sie einfach ein Spezifikum und beginnen Sie, Anfragen zu stellen Die LLM erzeugt realistische ., ? abwechslungsreiche Daten, die Ihren Schemas entsprechen ?, ? macht es perfekt für .

  • Entwicklung des Frontends während das Backend gebaut wird
  • Integrationsprüfung ohne auf echte APIs zu treffen
  • Offline-Entwicklung wenn die Konnektivität begrenzt ist
  • Belastungsprüfung ohne Quotenbedenken
  • Prototyping neue Funktionen schnell

Kombiniert mit API-Kontexten, erhalten Sie stattliche Mock-APIs, die Konsistenz über Anrufe und eine noch realistischere Simulation von Produktionssystemen bieten.

Die Zukunft der Mock-APIs ist dynamisch, intelligent und angetrieben von den gleichen LLMs, die moderne Entwicklungstools betreiben Willkommen in der neuen Ära des API-Mocking

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.