REST service/ gRPC service /whatever service)を公開するプログラムを想像してください。これは、いくつかのサードパーティライブラリを使用します。これらのライブラリは、何か問題が発生した場合に例外をスローします。たとえば、ユーザーが許可されていないものにアクセスしようとした場合。
ここでの問題は、リクエストが正しいかどうか、またはユーザーに十分な権限があるかどうかを事前に確認できないことです。そのため、サードパーティのライブラリにリクエストを送信し、例外を取得します。
これらの例外をトップレベルでキャッチして、このようなステータスコードにマッピングするのは良い習慣ですか?
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;
次に、エラーオブジェクトを含むステータスコードを返します。
return new ErrorResponse
{
Error = new ErrorDescription
{
Message = ex.Message,
Type = ex.GetType().Name
}
};
このアプローチを使用することで得られる利点:
短所:
これを行う正しい方法は何ですか?
編集:リクエストされたので、エラーマッピングが非常に似ている、gRPCサービスに対して私が行うことは次のとおりです。
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);
}
例外の正規化とそれらの適切な処理に問題はありません。クラスErrorResponse
は、RESTサービスへの呼び出しを処理するための適切なアプローチのようです。
ここに改善の余地があるものがある場合、それは静的エラー処理アプローチです。可能性のある例外/エラーコードのリストは明日簡単に増加する可能性があり、他の場合はこの速度で巨大なものになる可能性があります。
2つのメソッドbool CanHandle(Exception)
およびErrorResponse Handle(Exception)
でErrorManager
インターフェイスのリストを保持するErrorHandler
クラスを作成することを検討してください。
例外が発生すると、ErrorManager
は、例外を含むErrorHandler
を呼び出して、登録されている各CanHandle
を愚かにチェックします。それがtrueを返すと、チェックが停止し、ErrorHandler
がハンドラーのHandle
メソッドを呼び出さないようにします。次に、考えられるErrorHandler
ごとにErrorResponse
を作成します(例外ごとに作成する必要はありません)。
この動的なアプローチにより、プログラムでErrorHandler
クラスを登録したり、必要に応じてデータベースからロードしたりできるようになります。さらに重要なことは、プログラムでErrorHandler
クラスを登録することを決定した場合、これらのハンドラーのロード方法を変更することを決定したとしても、プログラムに影響をほとんどまたはまったく与えずにそれを行うことができます。本質的には、エラー処理の将来性を保証します。
賢明な言葉:例外のハンドラーが見つからない場合の計画を立ててください。これはおそらくHttpStatusCode.InternalServerError
。例外を「常に処理する」ハンドラーを作成することもできますが、技術的にはknownの可能性のある例外の管理について話しているため、予期しない例外は不明な例外であり、ほとんどの場合、他のエラーと同じように扱われるだけでなく、フラグを立てるべきです。
私はあなたのアプローチが好きですが、エラー応答の本文でクライアントに送信されるものも翻訳します。あなたはサードパーティのライブラリを制御できないと言っているので、サードパーティのライブラリが機密情報をクライアントに漏洩するかどうかもわかりません。申し訳ありませんが安全です。内部ログに例外を記録し、クライアントがエラーについて知る必要のある最小限の情報のみを伝達します。