it-swarm.com.de

Zuordnung von Ausnahmen zur Fehlerantwort

Stellen Sie sich ein Programm vor, das einen REST service/ gRPC-Service /welcher Dienst auch immer verfügbar macht, der mehrere Bibliotheken von Drittanbietern verwendet. Diese Bibliotheken können natürlich Ausnahmen auslösen, wenn etwas schief geht. Zum Beispiel, wenn der Benutzer versucht hat, auf etwas zuzugreifen, das er nicht darf.

Das Problem hierbei ist, dass es nicht möglich ist, vorher zu überprüfen, ob die Anforderung korrekt ist oder ob der Benutzer über genügend Rechte verfügt. Also senden wir die Anfrage an die Bibliothek eines Drittanbieters und erhalten eine Ausnahme.

Ist es empfehlenswert, diese Ausnahmen auf der obersten Ebene abzufangen und sie solchen Statuscodes zuzuordnen?

var statusCode = HttpStatusCode.InternalServerError;
if (ex is ArgumentException || ex is ResourceDoesntExistException)
    statusCode = HttpStatusCode.BadRequest;
else if (ex is UnauthorizedAccessException)
    statusCode = HttpStatusCode.Forbidden;
else if (ex is CustomerNotFoundException)
    statusCode = HttpStatusCode.NotFound;

und geben Sie dann den Statuscode mit einem Fehlerobjekt zurück:

return new ErrorResponse
{
    Error = new ErrorDescription
    {
        Message = ex.Message,
        Type = ex.GetType().Name
    }
};

Vorteile, die ich mit diesem Ansatz sehe:

  • Im Programm ist es uns egal, ob wir einen REST Service oder einen SOAP Service oder was auch immer) verfügbar machen. Wirf einfach eine Ausnahme aus, es wird sein später richtig gehandhabt.
  • Der Anrufer erhält genügend und korrekte Informationen, wenn etwas schief geht (solange die Ausnahmen aussagekräftige Namen und Informationen haben).
  • Die Protokollierung kann auch zentralisiert werden. Alle nicht behandelten Ausnahmen werden genau dort protokolliert, wo wir sie in Fehlerantworten umwandeln.

Nachteile:

  • Es fühlt sich ein wenig "hacky" an.
  • ?

Was ist der richtige Weg, um dies zu tun?


Bearbeiten: Da es angefordert wurde, mache ich Folgendes für gRPC-Dienste, bei denen die Fehlerzuordnung ziemlich ähnlich ist:

private RpcException GenerateRpcException(Exception ex)
{
    var statusCode = StatusCode.Unknown;

    if (ex is ArgumentException || ex is ResourceDoesntExistException)
        statusCode = StatusCode.InvalidArgument;
    else if (ex is UnauthorizedAccessException)
        statusCode = StatusCode.PermissionDenied;
    else if (ex is CustomerNotFoundException)
        statusCode = StatusCode.NotFound;

    var status = new Status(statusCode, ex.Message);
    var exceptionName = ex.GetType().Name;

    var rpcMetadata = new Metadata
    {
        { "exception_name", exceptionName }
    };
    return new RpcException(status, rpcMetadata);
}
7
CommonGuy

Es ist nichts Falsches daran, Ausnahmen zu normalisieren und richtig zu behandeln. Ihre Klasse ErrorResponse scheint der richtige Ansatz für die Bearbeitung eines Aufrufs Ihres REST -Dienstes) zu sein.

Wenn es hier etwas gibt, das verbessert werden könnte, handelt es sich um einen statischen Fehlerbehandlungsansatz. Die Liste möglicher Ausnahmen/Fehlercodes könnte morgen leicht wachsen, und Ihre Liste wird bei dieser Geschwindigkeit ungeheuerlich.

Erstellen Sie eine ErrorManager -Klasse, die eine Liste von ErrorHandler -Schnittstellen mit zwei Methoden enthält: bool CanHandle(Exception) und ErrorResponse Handle(Exception)

Ihr ErrorManager überprüft bei einer Ausnahme dumm jedes registrierte ErrorHandler mit einem Aufruf von CanHandle mit der Ausnahme. Wenn true zurückgegeben wird, wird die Prüfung beendet und Sie geben Ihre ErrorHandler vom Aufrufen der Handle -Methode Ihres Handlers zurück. Sie erstellen dann ein ErrorHandler für jedes mögliche ErrorResponse (und nicht unbedingt für jede Ausnahme).

Dieser dynamische Ansatz bietet Ihnen die Flexibilität, die Klassen ErrorHandler programmgesteuert zu registrieren oder aus einer Datenbank zu laden, wenn Sie dies wünschen. Noch wichtiger ist, dass Sie, wenn Sie sich entscheiden, die Klassen ErrorHandler jetzt programmgesteuert zu registrieren, falls Sie sich entscheiden, die Art und Weise zu ändern, wie Sie diese Handler laden, dies ohne oder mit nur geringen Auswirkungen auf Ihr Programm tun können. Im Wesentlichen sichern Sie Ihre Fehlerbehandlung zukunftssicher.

Ein Wort an die Weisen: Haben Sie einen Plan, wann Sie keinen Handler für eine Ausnahme finden. Dies ist wahrscheinlich am besten ein HttpStatusCode.InternalServerError. Sie könnten zwar einen Handler erstellen, der Ausnahmen "immer behandelt", aber ich würde davon abraten, da es sich technisch gesehen um die Verwaltung von bekannten möglichen Ausnahmen handelt und jede Ausnahme, die nicht erwartet wird, eine unbekannte Ausnahme ist und sollte auf jeden Fall rot markiert und nicht nur wie jeder andere Fehler behandelt werden.

6
Neil

Ich mag Ihren Ansatz, außer dass ich auch übersetzen würde, was an den Client im Hauptteil der Fehlerantwort geht. Da Sie sagen, dass Sie keine Kontrolle über die Bibliotheken von Drittanbietern haben, wissen Sie auch nicht, ob diese vertrauliche Informationen an den Client weitergeben. Besser sicher als leid: Protokollieren Sie die Ausnahme in Ihren internen Protokollen und geben Sie nur die Mindestinformationen weiter, die der Client über den Fehler wissen muss.

1
user285148