5.8 KiB
API Versioning Implementation
Übersicht
Dieses Dokument beschreibt die implementierte Versionierungsstrategie für die Meldestelle API. Das System unterstützt sowohl DTO-Versionierung als auch API-Versionierung für eine saubere Evolution der API.
Architektur
1. DTO Versionierung
Alle DTOs implementieren das VersionedDto Interface, welches folgende Eigenschaften bereitstellt:
interface VersionedDto {
val schemaVersion: String
val dataVersion: Long?
}
Beispiel Implementation:
@Serializable
@Since("1.0")
data class ArtikelDto(
@Serializable(with = UuidSerializer::class)
val id: Uuid,
val bezeichnung: String,
// ... andere Felder
override val schemaVersion: String = "1.0",
override val dataVersion: Long? = null
) : VersionedDto
2. Version Manager
Der VersionManager verwaltet API-Versionen und Kompatibilität:
object VersionManager {
const val CURRENT_API_VERSION = "1.0"
val SUPPORTED_VERSIONS = listOf("1.0")
val DEPRECATED_VERSIONS = emptyList<String>()
const val MINIMUM_CLIENT_VERSION = "1.0"
}
3. API Versioning Plugin
Das Ktor-Plugin VersioningPlugin behandelt:
- Version-Header Validierung
- Automatische Version-Header in Responses
- Deprecation Warnings
- Unsupported Version Errors
Verwendung
Client-seitige Version Headers
Clients können die API-Version über Header spezifizieren:
GET /api/artikel
API-Version: 1.0
oder
GET /api/artikel
X-API-Version: 1.0
Server Response Headers
Der Server antwortet mit Version-Informationen:
HTTP/1.1 200 OK
API-Version: 1.0
X-Supported-Versions: 1.0
Versioned Responses
Verwende die Extension-Funktionen für versionierte Antworten:
// Einzelnes DTO
call.respondVersioned(HttpStatusCode.OK, artikelDto)
// Liste von DTOs
call.respondVersionedList(HttpStatusCode.OK, artikelList)
Migration System
VersionMigrator Interface
interface VersionMigrator<T : VersionedDto> {
fun migrate(dto: T, fromVersion: String, toVersion: String): T
fun canMigrate(fromVersion: String, toVersion: String): Boolean
}
Beispiel Migrator
class ArtikelDtoMigrator : VersionMigrator<ArtikelDto> {
override fun migrate(dto: ArtikelDto, fromVersion: String, toVersion: String): ArtikelDto {
return when {
fromVersion == "1.0" && toVersion == "1.1" -> migrateFrom1_0To1_1(dto)
else -> throw IllegalArgumentException("Unsupported migration")
}
}
private fun migrateFrom1_0To1_1(dto: ArtikelDto): ArtikelDto {
return dto.copy(
schemaVersion = "1.1",
// Neue Felder mit Standardwerten hinzufügen
)
}
}
Annotations
@Since(version)
Markiert, seit welcher Version ein DTO oder Feld verfügbar ist.
@Deprecated(version, message)
Markiert veraltete DTOs oder Felder.
@Until(version)
Markiert, bis zu welcher Version ein DTO oder Feld verfügbar war.
Best Practices
1. Neue API Version hinzufügen
- VersionManager aktualisieren:
const val CURRENT_API_VERSION = "1.1"
val SUPPORTED_VERSIONS = listOf("1.1", "1.0")
val DEPRECATED_VERSIONS = listOf("1.0")
- DTOs erweitern:
@Serializable
@Since("1.1")
data class ArtikelDto(
// Bestehende Felder...
@Since("1.1")
val neuesFeld: String? = null,
override val schemaVersion: String = "1.1"
) : VersionedDto
- Migrator implementieren:
class ArtikelDtoMigrator : VersionMigrator<ArtikelDto> {
override fun migrate(dto: ArtikelDto, fromVersion: String, toVersion: String): ArtikelDto {
return when {
fromVersion == "1.0" && toVersion == "1.1" -> migrateFrom1_0To1_1(dto)
// Weitere Migrationen...
}
}
}
2. Backward Compatibility
- Neue Felder sollten optional sein (nullable oder mit Standardwerten)
- Bestehende Felder nicht entfernen, sondern als @Deprecated markieren
- Migratoren für alle unterstützten Versionsübergänge bereitstellen
3. Breaking Changes
Bei Breaking Changes:
- Neue Major Version erstellen
- Alte Version als deprecated markieren
- Migration Path bereitstellen
- Dokumentation aktualisieren
Beispiel API Calls
Erfolgreiche Anfrage
GET /api/artikel
API-Version: 1.0
HTTP/1.1 200 OK
API-Version: 1.0
X-Supported-Versions: 1.0
Content-Type: application/json
{
"data": {
"id": "...",
"bezeichnung": "Test Artikel",
"schemaVersion": "1.0",
"dataVersion": 1
},
"version": {
"apiVersion": "1.0",
"supportedVersions": ["1.0"],
"deprecatedVersions": []
},
"timestamp": "2024-01-01T12:00:00Z"
}
Unsupported Version
GET /api/artikel
API-Version: 2.0
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Unsupported API version: 2.0",
"supportedVersions": ["1.0"],
"currentVersion": "1.0"
}
Deprecated Version Warning
GET /api/artikel
API-Version: 0.9
HTTP/1.1 200 OK
API-Version: 1.0
X-API-Version-Warning: Version 0.9 is deprecated
Testing
Das Versioning System wird durch VersioningTest.kt getestet:
./gradlew test --tests "at.mocode.VersioningTest"
Implementierte DTOs
Folgende DTOs wurden bereits mit Versionierung ausgestattet:
- ✅
ArtikelDto,CreateArtikelDto,UpdateArtikelDto - ✅
VereinDto,CreateVereinDto,UpdateVereinDto
Noch zu implementieren:
AbteilungDtoBewerbDtoDomaeneDtoStammdatenDtoTurnierDtoVeranstaltungDtoCommonDto(alle Klassen)SpecializedDto
Nächste Schritte
- Alle verbleibenden DTOs mit Versionierung ausstatten
- API Routes auf DTO-Verwendung umstellen
- Versioning Plugin in Application.kt aktivieren
- Client-seitige Version-Header Implementation
- Monitoring für Version-Usage implementieren