Ein lokales Profil bringt Request, Transport und Response-Vertrag zusammen
HTTP-Schnittstellen automatisch testen: Status, Header und JSON-Verträge
Eine HTTP-API kann sauber antworten und trotzdem den vereinbarten Vertrag brechen: Der Statuscode stimmt nicht, ein Pflicht-Header fehlt oder die JSON-Antwort enthält den falschen Typ. Genau diese Lücke schließt Iteration 3 von ZEUS Interface Quality mit einem kleinen, reproduzierbaren HTTP-Adapter.
Der Ablauf ist bewusst überschaubar: Eine lokale JSON-Anfrage trifft auf einen ausdrücklich beschriebenen HTTP-Endpunkt, danach werden Status, Header, Content-Type und Response-Schema geprüft. Beim Ergebnis bleibt der Adapter auf vertrautem Terrain: Wie bei JSON-, CSV- und Fixed-Width-Dateien gibt es VALID, INVALID, stabile Findings und die Exit-Codes 0, 1 und 2.
Die übergeordnete Idee steht im Hauptartikel zur automatischen Schnittstellenqualität. Die erste Iteration erklärt JSON Schema als lokalen Prüfvertrag, Iteration 2 zeigt CSV und Fixed-Width. Hier geht es nun um den HTTP-Strang – und ebenso um die Grenzen, die ihn in dieser Ausbaustufe bewusst klein halten.

Was Iteration 3 liefert
Diese Ausbaustufe ist ein bewusst begrenzter Durchstich, kein vollständiger API-Testmanager. Sie nimmt ein lokales Profil, optional eine lokale JSON-Anfrage und eine lokale JSON-Response-Schema-Datei entgegen. Danach ruft sie genau den beschriebenen Endpunkt auf – reproduzierbar und ohne versteckte Zusatzlogik.
- Request: optionales JSON-Schema wird vor dem Netzwerkaufruf geprüft.
- Transport: JDK-21-
HttpClientführt HTTP oder HTTPS mit Timeout aus; Redirects werden nicht automatisch verfolgt. - Response: erwarteter Status, Pflicht-Header und optionaler Media-Type werden geprüft.
- Datenvertrag: die Response muss gültiges UTF-8-JSON sein und gegen ein lokales JSON Schema passen.
- Ergebnis: Vertragsverletzungen liefern
INVALID; Profil-, Datei-, Request- und Transportfehler beenden die Prüfung mit Exit-Code 2. - Schutz: lokale Schema-Pfade bleiben unterhalb des Profilverzeichnisses; Request-Header-Werte und Response-Payloads landen nicht im Report.
Das HTTP-Profil als lokaler Vertrag
Das Profil beschreibt nur Regeln, die der Adapter in dieser Iteration tatsächlich prüfen kann. Es ist absichtlich kleiner als OpenAPI: Methode, URL, Header, Status und JSON-Schemas reichen für einen ersten reproduzierbaren HTTP-Nachweis. Gerade diese Begrenzung macht den Ablauf gut lesbar.
{
"format": "http",
"version": 1,
"method": "POST",
"url": "http://127.0.0.1:8080/deliveries",
"requestHeaders": {
"Content-Type": "application/json",
"Accept": "application/json"
},
"requestSchema": "delivery-request.schema.json",
"expectedStatus": 201,
"requiredResponseHeaders": ["Content-Type", "X-Request-Id"],
"responseContentType": "application/json",
"responseSchema": "delivery-response.schema.json",
"timeoutSeconds": 5
}
Die beiden Schemaangaben sind relative lokale Pfade. Der Adapter löst sie unterhalb des Profilverzeichnisses auf und verwirft Pfade, die durch .. oder Symlinks aus diesem Bereich herausführen. Die URL darf Credentials und Fragmente nicht enthalten. Header-Namen werden als HTTP-Token geprüft, Header-Werte dürfen keine Zeilenumbrüche enthalten.
Das ist keine vollständige Sicherheitsarchitektur – soll es auch nicht sein. Die Regeln verhindern aber zwei typische Überraschungen: Ein Testprofil zeigt nicht stillschweigend auf beliebige lokale Dateien, und geheime URL-Bestandteile wandern nicht unbemerkt in die Konfiguration.
Request vor dem Versand prüfen
Wenn das Profil ein requestSchema nennt, ist auch eine lokale Eingabedatei erforderlich. Der Adapter validiert sie, bevor er HttpClient.send aufruft. Ein fehlendes Pflichtfeld oder ein falscher Typ bleibt damit ein sauberer Request-Befund – und wird nicht mit einem Fehler der Gegenstelle vermischt.
{
"deliveryId": "DEL-1001",
"quantity": 3,
"email": "ops@example.org"
}
Eine Request-Schema-Verletzung landet im gemeinsamen Report. Die Pfade machen dabei ausdrücklich sichtbar, auf welcher Seite die Abweichung liegt:
{
"status" : "INVALID",
"valid" : false,
"findings" : [ {
"instancePath" : "/request/body/quantity",
"schemaPath" : "/request/schema/properties/quantity/type",
"keyword" : "type",
"message" : "should be integer"
} ]
}
Der konkrete Meldungstext hilft beim Lesen, ein Automatisierungsskript sollte jedoch auf status, Pfade und keyword reagieren. Wichtig ist außerdem der Seiteneffekt: Ein ungültiger Request wird vor dem Versand abgewiesen. Der Loopback-Test von Iteration 3 macht das sichtbar, indem der lokale Server in diesem Fall keinen Request empfangen darf.
Die HTTP-Anfrage reproduzierbar ausführen
Der Transport basiert auf dem JDK-HTTP-Client und braucht deshalb weder eine zusätzliche Laufzeitbibliothek noch Spring Boot. Methode, URL, Header und Timeout kommen aus dem Profil. Die Standardkonfiguration folgt keinen Redirects. So bleibt ein unerwarteter Wechsel des Zielpfads ein sichtbarer Fehler – statt zu einem stillen zweiten Aufruf zu werden.
$jar = "target/zeus-interface-quality-0.1.0-SNAPSHOT.jar"
$profile = "src/test/resources/fixtures/http/delivery.http-profile.json"
$input = "src/test/resources/fixtures/http/delivery-request.json"
java -jar $jar validate --input-format http --schema $profile --input $input --report json
$LASTEXITCODE
Für einen echten lokalen Lauf muss auf dem im Profil genannten Port ein HTTP-Endpunkt mit dem erwarteten Verhalten lauschen. Die automatisierten Tests nehmen dafür keinen öffentlichen Dienst, sondern einen lokalen Loopback-Server. Status, Header und JSON-Body bleiben so reproduzierbar, und der Test erzeugt keine externe Nebenwirkung.
Status, Header und Response-Schema prüfen
Eine Response ist erst dann vertragskonform, wenn mehrere Ebenen passen. Der Adapter hält die Abweichungen getrennt fest: Ein falscher Status landet unter /response/status, fehlende Pflicht-Header unter /response/headers/<name> und Schemaabweichungen unter /response/body/....
{
"accepted": true,
"deliveryId": "DEL-1001",
"requestId": "req-local-1001"
}
Der Content-Type wird als Media-Type verglichen; Parameter wie charset=utf-8 ändern nicht die Bewertung von application/json. Der Body wird strikt als UTF-8 decodiert und danach als JSON geparst. Eine kaputte JSON-Antwort ist deshalb eine Response-Vertragsverletzung mit Exit-Code 1. Ein nicht erreichbarer Server dagegen ist ein technischer Fehler mit Exit-Code 2.
{
"status" : "INVALID",
"valid" : false,
"findings" : [ {
"instancePath" : "/response/status",
"schemaPath" : "/expectedStatus",
"keyword" : "status",
"message" : "HTTP-Status 201 erwartet, 500 erhalten"
}, {
"instancePath" : "/response/headers/X-Request-Id",
"schemaPath" : "/requiredResponseHeaders",
"keyword" : "required",
"message" : "HTTP-Response enthält den erforderlichen Header nicht: X-Request-Id"
}, {
"instancePath" : "/response/body/accepted",
"schemaPath" : "/response/schema/properties/accepted/type",
"keyword" : "type",
"message" : "should be boolean"
} ]
}
Der Report enthält weder die vollständige Response-Payload noch Request-Header-Werte. So bleibt die erste Report-Schnittstelle klein, und das Risiko sinkt, dass Tokens, personenbezogene Daten oder große Antwortkörper in CI-Logs landen.
Findings und Exit-Codes lesen
| Fall | Beispiel | Ergebnis |
|---|---|---|
| VALID | Status, Header, JSON und Schema passen | Report, Exit 0 |
| INVALID | falscher Status, fehlender Header oder Response-Verletzung | Report, Exit 1 |
| Request ungültig | Request-Schema bricht vor dem Versand | Report, Exit 1 |
| Prüfung nicht möglich | ungültiges Profil, Datei- oder Transportfehler | kein Report, Exit 2 |
Diese Trennung ist im CI entscheidend. Exit-Code 1 bedeutet: Der Adapter konnte die Eingabe prüfen beziehungsweise die Schnittstelle erreichen, aber der Vertrag ist verletzt. Exit-Code 2 bedeutet: Die Prüfung selbst konnte nicht zuverlässig durchgeführt werden.
Warum der Kern unverändert bleibt
Der neue Adapter spricht dieselbe Validator-Schnittstelle wie die lokalen Datei-Adapter. Sein HTTP-spezifischer Teil liest das Profil, führt den Transport aus und übersetzt Abweichungen in Finding-Objekte. CLI und Report müssen dadurch nicht wissen, ob ein Befund aus einer JSON-Datei oder aus einer HTTP-Response stammt.
| Baustein | Verantwortung | Bewusste Grenze |
|---|---|---|
core |
Finding, Status, Ergebnis und Validator-Port | keine HTTP- oder Profilkenntnis |
adapter.http |
Profil, Request, JDK-Client und Response-Prüfungen | kein OpenAPI-Parser, keine Secret-Verwaltung |
adapter.jsonschema |
lokales Schema selbst und JSON-Knoten validieren | kein HTTP-Transport |
cli |
AUTO/HTTP-Auswahl, Report und Exit-Code | keine Orchestrierung mehrerer Requests |
Der automatisierte Nachweis
Die neuen Tests starten einen lokalen Loopback-Server und bleiben nicht beim Happy Path stehen. Der Testbestand deckt einen gültigen Request mit Response, einen ungültigen Request ohne Versand, falschen Status, fehlenden Header, falschen Response-Typ, kaputtes Response-JSON, die echte CLI-Ausgabe und einen nicht erreichbaren Transport ab.
🟢 Reproduzierbarer Ablauf
Im technischen Repository lässt sich der HTTP-Strang mit mvnw.cmd -B -Dtest=HttpValidatorTest test isoliert ausführen. Der vollständige Build mit mvnw.cmd -B test umfasst nach Iteration 3 insgesamt 70 Tests; zwei Windows-Fälle für symbolische Links bleiben übersprungen, wenn die lokale Berechtigung fehlt. Anschließend erzeugt mvnw.cmd -B package das ausführbare JAR.
Die Tests bleiben absichtlich lokal. Sie benötigen keinen externen Webdienst, senden keine Daten ins Internet und können erwarteten Status und Antwort-Header vollständig kontrollieren. Das ist ein belastbarer Nachweis für den Adapter – aber noch kein Beweis für die Verfügbarkeit oder Fachlichkeit einer produktiven Gegenstelle.
Was bewusst noch nicht enthalten ist
- kein OpenAPI-Parser und keine automatische Ableitung eines Profils aus einer OpenAPI-Datei;
- keine OAuth-, API-Key- oder mTLS-Verwaltung und keine Secret-Quelle;
- keine Redirects, kein Streaming und keine Mehrschritt- oder Mehrdatei-Szenarien;
- keine SFTP- oder FTP-Verbindung, keine Quarantäne und kein Retry-Modell;
- keine fachlichen Regeln über mehrere Requests oder Datensätze;
- keine Performance-, Last- oder Verfügbarkeitsaussage über eine reale API.
Diese Grenzen gehören zur Iteration; sie sind nicht bloß eine To-do-Liste. Ein kleiner HTTP-Vertrag mit lokaler Reproduzierbarkeit liefert bereits einen prüfbaren Baustein. Authentifizierung, OpenAPI und Betriebsverhalten kommen erst hinzu, wenn ein konkreter Anwendungsfall die zusätzlichen Regeln rechtfertigt.
Fazit: HTTP wird als Vertrag prüfbar
Iteration 3 verbindet den bisher lokalen Datenvertrag mit einem echten, aber bewusst kleinen HTTP-Ablauf. Ein Profil beschreibt Methode, URL, Header, erwarteten Status und lokale JSON-Schemas; der JDK-Client führt den Request aus und übersetzt Abweichungen in denselben Report wie die Datei-Adapter.
Der Nachweis bleibt reproduzierbar: Loopback-Tests decken gültige und ungültige Requests, Response-Fehler und Transportprobleme ab. HTTP ist damit als nächste Ausbaustufe greifbar, ohne OpenAPI, Authentifizierung und Betriebsreife vorwegzunehmen.
Die nächsten Entscheidungen bleiben offen: SFTP, ein vollständiger OpenAPI-Vertrag, Secret-Verwaltung oder weitere fachliche Regeln sind eigene Iterationen. Der Hauptartikel hält den Gesamtstand fest.
Code und Quellen
Technischer und redaktioneller Stand: 21. September 2026. Die Beispiele beziehen sich auf den lokalen Repository-Stand von Iteration 3.



tiny-tool.de
tiny-tool.de