This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
LLMApi-:-OpenAPI Dynamischer Mock-Generator - :-Lade jedes Spec.,-Mocke jede API
Wednesday, 05 November 2025
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-
Sie können die GitHub hier für das Projekt – alle öffentlichen Bereiche usw. –

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.
- Parses die Spezifikation
- Entdeckt alle Endpunkte
- Erzeugt realistische Mock-Daten mit einem LLM
- 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
- DynamicOpenApiManager Verwaltet geladene Spezifikationen und Routenabgleich
- OpenApiSpecLoader Dokumente und Parsen von OpenAPI
- OpenApiRequestHandler Erzeugt Antworten für abgestimmte Endpunkte
- PromptBuilder Erstellen von LLM-Prompten aus OpenAPI-Schemas
- 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
- Codes für den Antwortstatus Nur erfolgreiche Antworten werden verspottet
- Authentifizierung Auth Header werden akzeptiert, aber nicht validiert.
- Validierung Beantragung einer Validierung gegen Schemas wird nicht durchgesetzt
- Mitgliedstaat Keine aktuelle Datenbank Es werden jedes Mal neue Daten erzeugt, es sei denn mit Kontexten
- 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