Quel est le modèle pour envoyer plus de détails sur les erreurs au client à l'aide de gRPC?
Par exemple, supposons que j'ai un formulaire pour enregistrer un utilisateur, qui envoie un message
message RegisterUser {
string email = 1;
string password = 2;
}
où l'e-mail doit être correctement formaté et unique, et le mot de passe doit comporter au moins 8 caractères.
Si j'écrivais une API JSON, je retournerais une erreur 400 avec le corps suivant:
{
"errors": [{
"field": "email",
"message": "Email does not have proper format."
}, {
"field": "password",
"message": "Password must be at least 8 characters."
}],
}
et le client pourrait fournir des messages d'erreur Nice à l'utilisateur (c'est-à-dire en mettant en surbrillance le champ du mot de passe et en disant spécifiquement à l'utilisateur qu'il y a quelque chose de mal avec leur saisie).
Avec gRPC, existe-t-il un moyen de faire quelque chose de similaire? Il semble que dans la plupart des langues clientes, une erreur entraîne la levée d'une exception, sans aucun moyen de récupérer la réponse.
Par exemple, j'aimerais quelque chose comme
message ValidationError {
string field = 1;
string message = 2;
}
message RegisterUserResponse {
repeated ValidationError validation_errors = 1;
...
}
ou similaire.
Inclure des détails d'erreur supplémentaires dans les métadonnées de réponse. Cependant, assurez-vous toujours de fournir un code d'état et un message utiles. Dans ce cas, vous pouvez ajouter RegisterUserResponse
aux métadonnées.
Dans gRPC Java, cela ressemblerait à:
Metadata.Key<RegisterUserResponse> REGISTER_USER_RESPONSE_KEY =
ProtoUtils.keyForProto(RegisterUserResponse.getDefaultInstance());
...
Metadata metadata = new Metadata();
metadata.put(REGISTER_USER_RESPONSE_KEY, registerUserResponse);
responseObserver.onError(
Status.INVALID_ARGUMENT.withDescription("Email or password malformed")
.asRuntimeException(metadata));
Une autre option consiste à utiliser le google.rpc.Status
proto qui inclut un Any
supplémentaire pour details
. Le support arrive dans chaque langue pour gérer le type. En Java, cela ressemblerait à:
// This is com.google.rpc.Status, not io.grpc.Status
Status status = Status.newBuilder()
.setCode(Code.INVALID_ARGUMENT.getNumber())
.setMessage("Email or password malformed")
.addDetails(Any.pack(registerUserResponse))
.build();
responseObserver.onError(StatusProto.toStatusRuntimeException(status));
google.rpc.Status
est plus propre dans certaines langues car les détails de l'erreur peuvent être transmis comme une seule unité. Il indique également clairement quelles parties de la réponse sont liées aux erreurs. Sur le fil, il utilise toujours des métadonnées pour transmettre les informations supplémentaires.
Vous pouvez également être intéressé par error_details.proto qui contient certains types d'erreurs courants.
I discuté de ce sujet pendant CloudNativeCon. Vous pouvez consulter les diapositives et l'enregistrement lié sur YouTube.