TL;DR
URL-Versionierung (/v1/pets) ist die praktischste API-Versionierungsstrategie für die meisten Teams. Sie ist sichtbar, cachefähig und einfach zu testen. Header-Versionierung und Content Negotiation sind "reiner" REST, aber komplexer. Die moderne PetstoreAPI verwendet URL-Versionierung mit semantischer Versionierung und klaren Deprecation-Richtlinien.
Einleitung
Ihre API benötigt eine Breaking Change (bruchverursachende Änderung). Sie ändern das Antwortformat für /pets von einem einfachen Array in ein umhülltes Objekt mit Paginierungsmetadaten. Bestehende Clients werden nicht mehr funktionieren. Was tun Sie?
Sie benötigen API-Versionierung. Aber welche Strategie? URL-Versionierung (/v1/pets vs. /v2/pets)? Header-Versionierung (Accept: application/vnd.petstore.v1+json)? Content Negotiation? Jeder Ansatz hat leidenschaftliche Befürworter und starke Meinungen.
Die Antwort: URL-Versionierung ist für die meisten Teams die beste Wahl. Sie ist pragmatisch, sichtbar und funktioniert mit allen HTTP-Tools. Header-Versionierung und Content Negotiation sind theoretisch sauberer, fügen aber eine Komplexität hinzu, die die meisten Teams nicht benötigen.
Die moderne PetstoreAPI verwendet URL-Versionierung mit semantischer Versionierung und klaren Deprecation-Richtlinien. Die aktuelle Version ist v1, wobei v2 für zukünftige Breaking Changes geplant ist.
In diesem Leitfaden lernen Sie die drei wichtigsten Versionierungsstrategien, deren Kompromisse und wie Sie die Versionierung korrekt implementieren, am Beispiel der modernen PetstoreAPI.
Warum APIs Versionierung benötigen
APIs entwickeln sich weiter. Sie fügen Funktionen hinzu, beheben Fehler und verbessern Designs. Manchmal führen diese Änderungen dazu, dass bestehende Clients nicht mehr funktionieren.
Breaking Changes
Änderungen, die bestehende Clients beeinträchtigen:
1. Entfernen von Feldern:
// v1
{"id": "123", "name": "Fluffy", "age": 3}
// v2 (Breaking Change: age entfernt)
{"id": "123", "name": "Fluffy"}
2. Ändern von Feldtypen:
// v1
{"price": "19.99"}
// v2 (Breaking Change: String zu Zahl)
{"price": 19.99}
3. Ändern der Antwortstruktur:
// v1 (einfaches Array)
[{"id": "123"}]
// v2 (Breaking Change: umhülltes Objekt)
{"data": [{"id": "123"}], "pagination": {...}}
4. Ändern der URL-Struktur:
// v1
GET /pet/123
// v2 (Breaking Change: Plural)
GET /pets/123
5. Ändern der Authentifizierung:
// v1: API-Schlüssel in der Abfrage
GET /pets?api_key=xxx
// v2 (Breaking Change: Bearer Token)
GET /pets
Authorization: Bearer xxx
Nicht-Breaking Changes
Änderungen, die Clients nicht beeinträchtigen:
- Hinzufügen neuer Endpunkte
- Hinzufügen optionaler Felder zu Anfragen
- Hinzufügen neuer Felder zu Antworten (Clients sollten unbekannte Felder ignorieren)
- Hinzufügen neuer Abfrageparameter
- Hinzufügen neuer HTTP-Methoden zu bestehenden Ressourcen
Die Versionierungsentscheidung
Wenn Sie eine Breaking Change benötigen, haben Sie zwei Optionen:
1. Alle Clients zum Upgrade zwingen – Einfach, aber bricht bestehende Integrationen
2. Mehrere Versionen unterstützen – Mehr Aufwand, aber bewahrt die Abwärtskompatibilität
Die meisten öffentlichen APIs wählen Option 2. Versionierung ermöglicht es Ihnen, die API weiterzuentwickeln und Clients gleichzeitig Zeit zur Migration zu geben.
URL-Versionierung
Die URL-Versionierung platziert die Versionsnummer im URL-Pfad.
Funktionsweise
GET /v1/pets
GET /v2/pets
Die Version ist Teil des Ressourcenbezeichners. Verschiedene Versionen sind verschiedene Ressourcen.
Vorteile
1. Sichtbar und explizit
Die Version ist in der URL enthalten. Sie können sie in Logs, im Browserverlauf und in der Dokumentation sehen. Keine versteckten Header, die man sich merken müsste.
2. Einfach zu testen
curl https://petstoreapi.com/v1/pets
curl https://petstoreapi.com/v2/pets
Sie können beide Versionen mit einfachen HTTP-Anfragen testen.
3. Funktioniert mit allen HTTP-Tools
Browser, Caches, Proxys und Load Balancer sehen verschiedene URLs. Sie können jede Version unabhängig routen, cachen und protokollieren.
4. Einfach für Clients
Clients ändern einfach die URL. Keine benutzerdefinierten Header oder Content-Negotiation-Logik.
5. Einfach zu verwerfen (deprecate)
Sie können /v1-Endpunkte entfernen, ohne /v2 zu beeinträchtigen.
Nachteile
1. Nicht "reines" REST
REST-Puristen argumentieren, dass /v1/pets/123 und /v2/pets/123 dieselbe Ressource sind und daher dieselbe URL haben sollten. Die Version sollte in Headern oder der Content Negotiation enthalten sein.
2. URL-Verschmutzung
Ihre API hat mehrere URL-Räume: /v1/*, /v2/*, etc.
3. Schwerer, einzelne Ressourcen zu versionieren
Wenn Sie nur einen Endpunkt versionieren möchten, müssen Sie die gesamte API versionieren oder Inkonsistenzen schaffen.
Implementierung
Hauptversion in der URL:
/v1/pets
/v2/pets
Keine Nebenversionen einschließen:
❌ /v1.2/pets (zu granular)
✅ /v1/pets (nur Hauptversion)
Verwenden Sie intern semantische Versionierung:
- v1.0.0 - Erste Veröffentlichung
- v1.1.0 - Neue Felder hinzufügen (nicht-bruchverursachend)
- v1.2.0 - Neue Endpunkte hinzufügen (nicht-bruchverursachend)
- v2.0.0 - Breaking Changes (neue URL: /v2)
Die moderne PetstoreAPI verwendet URL-Versionierung mit /v1 als aktueller Version.
Header-Versionierung
Die Header-Versionierung platziert die Version in einem benutzerdefinierten HTTP-Header.
Funktionsweise
GET /pets
API-Version: 1
GET /pets
API-Version: 2
Die URL bleibt gleich. Der Header gibt die Version an.
Vorteile
1. Saubere URLs
/pets ist für alle Versionen gleich. Kein /v1- oder /v2-Präfix.
2. "RESTful-er"
Der Ressourcenbezeichner (/pets/123) ändert sich nicht. Die Darstellung ändert sich basierend auf dem Header.
3. Granulare Versionierung
Sie können einzelne Ressourcen versionieren:
GET /pets
API-Version: 2
GET /orders
API-Version: 1
Nachteile
1. Unsichtbar
Die Version ist nicht in der URL enthalten. Sie können sie nicht in Logs oder im Browserverlauf sehen, ohne die Header zu prüfen.
2. Schwerer zu testen
curl -H "API-Version: 1" https://petstoreapi.com/pets
curl -H "API-Version: 2" https://petstoreapi.com/pets
Sie müssen daran denken, den Header einzuschließen.
3. Caching-Komplexität
Caches müssen den API-Version-Header berücksichtigen. Sie benötigen Vary: API-Version in den Antworten.
4. Client-Komplexität
Clients benötigen eine benutzerdefinierte Header-Logik. Nicht alle HTTP-Clients machen dies einfach.
5. Uneindeutigkeit der Standardversion
Was passiert, wenn der Client den Header nicht sendet? Sie benötigen eine Standardeinstellung, was implizites Verhalten erzeugt.
Implementierung
Benutzerdefinierter Header:
API-Version: 1
Oder verwenden Sie den Accept-Header:
Accept: application/vnd.petstore.v1+json
Vary-Header einschließen:
Vary: API-Version
Dies weist Caches an, den Header beim Caching zu berücksichtigen.
Content Negotiation
Content Negotiation verwendet den Accept-Header mit benutzerdefinierten Medientypen.
Funktionsweise
GET /pets
Accept: application/vnd.petstore.v1+json
GET /pets
Accept: application/vnd.petstore.v2+json
Die Version ist Teil des Medientyps.
Vorteile
1. Am "RESTful-sten"
So wurde REST konzipiert. Verschiedene Darstellungen derselben Ressource.
2. Folgt HTTP-Standards
Verwendet Standard-HTTP-Content Negotiation.
3. Unterstützt mehrere Formate
Sie können gleichzeitig versionieren und formatieren:
Accept: application/vnd.petstore.v1+json
Accept: application/vnd.petstore.v1+xml
Nachteile
1. Komplex
Clients müssen Medientypen und Content Negotiation verstehen.
2. Schwerer zu testen
curl -H "Accept: application/vnd.petstore.v1+json" https://petstoreapi.com/pets
3. Schlechte Tool-Unterstützung
Viele HTTP-Clients und -Tools gehen nicht gut mit benutzerdefinierten Medientypen um.
4. Caching-Komplexität
Caches müssen den Accept-Header berücksichtigen. Sie benötigen Vary: Accept.
5. Überdimensioniert für die meisten APIs
Die meisten APIs benötigen dieses Maß an Komplexität nicht.
Implementierung
Anbieterspezifischer Medientyp:
Accept: application/vnd.petstore.v1+json
Antwort:
Content-Type: application/vnd.petstore.v1+json
Vary: Accept
Wie die moderne PetstoreAPI Versionierung implementiert
Die moderne PetstoreAPI verwendet URL-Versionierung mit klaren Richtlinien.
Aktuelle Version: v1
https://petstoreapi.com/v1/pets
https://petstoreapi.com/v1/orders
https://petstoreapi.com/v1/users
Alle Endpunkte befinden sich unter /v1.
Versions-Antwort-Header
Jede Antwort enthält die API-Version:
X-API-Version: 1.2.0
Dies zeigt die genaue Version (Major.Minor.Patch), obwohl die URL nur die Hauptversion anzeigt.
Deprecation-Warnungen
Wenn eine Version als veraltet markiert ist, enthalten die Antworten:
Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
Link: <https://docs.petstoreapi.com/migration/v1-to-v2>; rel="deprecation"
Deprecation– Zeigt an, dass die Version veraltet istSunset– Wann die Version entfernt wirdLink– Migrationsleitfaden
Versionserkennung
Der Root-Endpunkt listet verfügbare Versionen auf:
GET https://petstoreapi.com/
{
"versions": [
{
"version": "v1",
"status": "current",
"docsUrl": "https://docs.petstoreapi.com/v1"
}
]
}
Semantische Versionierung
Die moderne PetstoreAPI folgt intern der semantischen Versionierung:
- Major (v1, v2) – Breaking Changes, neue URL
- Minor (v1.1, v1.2) – Neue Funktionen, abwärtskompatibel
- Patch (v1.1.1, v1.1.2) – Fehlerbehebungen, abwärtskompatibel
Nur Hauptversionen erscheinen in URLs.
Testen von API-Versionen mit Apidog
Apidog hilft Ihnen, mehrere API-Versionen zu testen.
Mehrere Versionen importieren
OpenAPI-Spezifikationen für jede Version importieren:
petstore-v1.yaml → Umgebung: v1
petstore-v2.yaml → Umgebung: v2
Tests für alle Versionen ausführen
Erstellen Sie Test-Suites, die für beide Versionen ausgeführt werden:
// Test v1
pm.environment.set("baseUrl", "https://petstoreapi.com/v1");
pm.sendRequest(pm.environment.get("baseUrl") + "/pets");
// Test v2
pm.environment.set("baseUrl", "https://petstoreapi.com/v2");
pm.sendRequest(pm.environment.get("baseUrl") + "/pets");
Versionsspezifisches Verhalten validieren
Testen Sie, ob sich v1 und v2 unterschiedlich verhalten:
// v1 gibt ein einfaches Array zurück
pm.test("v1 returns array", function() {
pm.expect(pm.response.json()).to.be.an('array');
});
// v2 gibt ein umhülltes Objekt zurück
pm.test("v2 returns wrapped object", function() {
pm.expect(pm.response.json()).to.have.property('data');
pm.expect(pm.response.json()).to.have.property('pagination');
});
Deprecation-Header prüfen
Testen Sie, ob veraltete Versionen die entsprechenden Header enthalten:
pm.test("Deprecated version includes headers", function() {
pm.response.to.have.header("Deprecation");
pm.response.to.have.header("Sunset");
});
Strategie zur Versionsdeprecation
Wie alte Versionen ohne Beeinträchtigung der Clients veraltet werden können.
1. Deprecation frühzeitig ankündigen
Geben Sie Clients mindestens 6-12 Monate Vorlaufzeit:
Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
2. Migrationsleitfaden bereitstellen
Dokumentieren Sie alle Breaking Changes und wie man migriert:
Link: <https://docs.petstoreapi.com/migration/v1-to-v2>; rel="deprecation"
3. Nutzung überwachen
Verfolgen Sie, welche Clients noch veraltete Versionen verwenden:
X-API-Version: 1.2.0
X-Client-ID: abc123
Kontaktieren Sie Clients bei Bedarf direkt.
4. Schrittweise Abschaltung
Entfernen Sie die Version nicht sofort:
- Monat 1-6: Deprecation ankündigen
- Monat 7-9: Deprecation-Header hinzufügen
- Monat 10-11: Ratenbegrenzungen für die veraltete Version reduzieren
- Monat 12: Veraltete Version entfernen
5. Dokumentation beibehalten
Auch nach der Entfernung sollten Sie die Dokumentation für die alte Version aufbewahren. Clients könnten sie als Referenz benötigen.
Fazit
URL-Versionierung ist die praktischste API-Versionierungsstrategie für die meisten Teams. Sie ist sichtbar, einfach zu testen und funktioniert mit allen HTTP-Tools. Header-Versionierung und Content Negotiation sind "reiner" REST, aber komplexer.
Die moderne PetstoreAPI verwendet URL-Versionierung mit /v1 als aktueller Version, semantischer Versionierung intern und klaren Deprecation-Richtlinien. Dieser Ansatz balanciert Pragmatismus mit gutem API-Design.
Nutzen Sie Apidog, um mehrere API-Versionen zu testen, versionsspezifisches Verhalten zu validieren und reibungslose Migrationen zwischen den Versionen sicherzustellen.
FAQ
Sollte ich URL-Versionierung oder Header-Versionierung verwenden?
Verwenden Sie URL-Versionierung, es sei denn, Sie haben einen speziellen Grund, dies nicht zu tun. Sie ist einfacher, sichtbarer und leichter zu testen. Header-Versionierung ist "RESTful-er", fügt aber eine Komplexität hinzu, die die meisten Teams nicht benötigen.
Wie viele Versionen sollte ich gleichzeitig unterstützen?
Unterstützen Sie maximal 2 Versionen: die aktuelle und die vorherige. Mehr zu unterstützen, schafft Wartungsaufwand. Geben Sie Clients 6-12 Monate Zeit zur Migration, dann entfernen Sie alte Versionen.
Sollte ich ab v0 oder v1 versionieren?
Beginnen Sie mit v1. v0 impliziert Instabilität. Wenn Ihre API nicht stabil genug für v1 ist, veröffentlichen Sie sie noch nicht öffentlich.
Muss ich jeden Endpunkt versionieren?
Nein. Versionieren Sie nur, wenn Sie Breaking Changes vornehmen. Wenn Sie neue Endpunkte hinzufügen, ohne bestehende zu ändern, benötigen Sie keine neue Version.
Was ist mit Nebenversionen in URLs?
Fügen Sie keine Nebenversionen in URLs ein. Verwenden Sie /v1, nicht /v1.2. Nebenversionen sind abwärtskompatibel, daher müssen Clients keine URLs ändern.
Wie gehe ich mit versionsspezifischen Fehlern um?
Beheben Sie Fehler in allen unterstützten Versionen. Wenn ein Fehler nur in v1 existiert, beheben Sie ihn in v1. Zwingen Sie Clients nicht, für Fehlerbehebungen auf v2 zu aktualisieren.
Sollte ich semantische Versionierung verwenden?
Ja, intern. Verfolgen Sie Major.Minor.Patch-Versionen, aber stellen Sie nur Hauptversionen in URLs bereit. Dies gibt Ihnen Flexibilität für nicht-bruchverursachende Änderungen.
Was, wenn ich nur einen Endpunkt versionieren muss?
Bei der URL-Versionierung müssten Sie die gesamte API versionieren oder Inkonsistenzen schaffen. Dies ist ein Kompromiss. Die meisten Teams akzeptieren die Versionierung der gesamten API aus Gründen der Einfachheit.
