Zum Inhalt

ADR-008: Route-Reihenfolge in NestJS-Controllern

Stand: 12.08.2026 16:55 Branch: main Status: Akzeptiert

Datum, Uhrzeit Version Änderung Autor
12.08.2026 16:55 1.1 Verweis auf historischen UC00-Benutzervertrag an neuen Nachweisort angepasst Codex
01.08.2026 14:55 1.0 Kopfbereich vereinheitlicht David Mittig

Datum: 2024-01
Kontext: UC00 Schritt 4 – OpenAPI Spezifikation, Block 3 User-Management


Kontext

In der OpenAPI-Spezifikation Block 3 (docs/evidence/historical/api/uc00/openapi-block3-users.yaml) existieren folgende Pfade im User-Management:

GET  /users/invitations              ← statische Route
GET  /users/{userId}                 ← parametrisierte Route
DELETE /users/invitations/{invitationId}

Ein HTTP-Router verarbeitet eingehende Requests sequenziell nach Reihenfolge der Routendefinitionen. Wenn /users/{userId} vor /users/invitations registriert wird, interpretiert der Router invitations als Wert für den Parameter userId — der Request landet am falschen Handler.

Beispiel des Fehlers (falsche Reihenfolge):

GET /users/invitations
→ Router matched: GET /users/{userId}
→ userId = "invitations"
→ Datenbankabfrage: SELECT * FROM users WHERE id = 'invitations'
→ Ergebnis: 404 Not Found (statt Liste der Einladungen)

Entscheidung

Statische Routen müssen in NestJS-Controllern immer vor parametrisierten Routen deklariert werden.

Konkret für den UsersController:

@Controller('users')
export class UsersController {

  // ✅ RICHTIG: Statische Routen zuerst
  @Get('invitations')
  listInvitations() { ... }

  @Delete('invitations/:invitationId')
  revokeInvitation(@Param('invitationId') id: string) { ... }

  @Post('invite')
  inviteUser() { ... }

  // Parametrisierte Routen danach
  @Get(':userId')
  getUser(@Param('userId') id: string) { ... }

  @Patch(':userId')
  updateUser(@Param('userId') id: string) { ... }

  @Delete(':userId')
  deleteUser(@Param('userId') id: string) { ... }

  @Patch(':userId/role')
  updateUserRole(@Param('userId') id: string) { ... }

  @Patch(':userId/status')
  updateUserStatus(@Param('userId') id: string) { ... }
}

Begründung

  • NestJS verarbeitet Route-Handler in der Reihenfolge ihrer Deklaration
  • Statische Segmente (invitations) haben höhere Spezifität als Parameter (:userId)
  • Diese Reihenfolge muss im Code explizit eingehalten werden — NestJS sortiert nicht automatisch nach Spezifität (anders als z.B. Express mit bestimmten Plugins)
  • Das Muster ist in der NestJS-Dokumentation explizit empfohlen

Konsequenzen

  • Positiv: Kein Routing-Bug, korrekte Handler-Zuordnung garantiert
  • Positiv: Explizite Reihenfolge macht die Intention im Code sichtbar
  • Negativ (minimal): Entwickler müssen diese Konvention kennen und einhalten
  • Massnahme: Code-Review-Checkliste für Controller-Reihenfolge

Betroffene Dateien

Datei Anmerkung
backend/src/users/users.controller.ts Reihenfolge wie oben einhalten
docs/evidence/historical/api/uc00/openapi-block3-users.yaml Pfade dokumentiert
docs/api/api-overview.md Hinweis in Endpoint-Tabelle Block 3

Verwandte ADRs

  • ADR-007: API-Basis-URL (api.divelogix360.ch/v1)