protovalidate
est une série de bibliothèques conçues pour valider les messages Protobuf au moment de l'exécution sur la base de règles de validation définies par l'utilisateur. Propulsé par le Common Expression Language (CEL) de Google, il fournit une base flexible et efficace pour définir et évaluer des règles de validation personnalisées. L'objectif principal de protovalidate
est d'aider les développeurs à garantir la cohérence et l'intégrité des données sur l'ensemble du réseau sans nécessiter de code généré.
Note
protovalidate
est le successeur spirituel de protoc-gen-validate. Il ne nécessite aucune génération de code et prend en charge les contraintes personnalisées.
Nous recommandons que les projets nouveaux et existants utilisent protovalidate
au lieu de protoc-gen-validate
.
Lisez notre article de blog si vous souhaitez en savoir plus sur les limites de protoc-gen-validate
et sur la façon dont nous avons conçu protovalidate
pour être meilleur.
Ce référentiel est le cœur du projet protovalidate
. Il contient :
protovalidate
protoc-gen-validate
.proto
utilisant protovalidate
protovalidate
Les implémentations d'exécution de protovalidate
peuvent être trouvées dans leurs propres référentiels :
protovalidate-go
(version bêta)protovalidate-cc
(version bêta)protovalidate-java
(version bêta)protovalidate-python
(version bêta)protovalidate-ts
(à venir)Vous souhaitez ajouter la prise en charge d’une autre langue ? Consultez nos directives de contribution.
Pour définir des contraintes dans vos messages Protobuf, importez buf/validate/validate.proto
dans vos fichiers .proto
:
syntax = "proto3" ;
package my.package ;
import "buf/validate/validate.proto" ;
buf
Ajoutez une dépendance sur buf.build/bufbuild/protovalidate
au buf.yaml
de votre module :
version : v1
# <snip>
deps :
- buf.build/bufbuild/protovalidate
# <snip>
Après avoir modifié votre buf.yaml
, n'oubliez pas d'exécuter buf mod update
pour vous assurer que vos dépendances sont à jour.
protoc
Ajoutez un chemin d'importation (indicateur -I
) pointant vers le contenu du répertoire proto/protovalidate
à votre invocation de protoc
:
protoc
-I ./vendor/protovalidate/proto/protovalidate
# <snip>
Les contraintes de validation peuvent être appliquées à l'aide du package buf.validate
Protobuf. Les règles sont spécifiées directement dans les fichiers .proto
.
Considérons quelques exemples :
Validation de champ scalaire : pour un message User
de base, nous pouvons imposer des contraintes telles qu'une longueur minimale pour le nom de l'utilisateur.
syntax = "proto3" ;
import "buf/validate/validate.proto" ;
message User {
// User's name, must be at least 1 character long.
string name = 1 [ (buf.validate .field ) .string .min_len = 1 ];
}
Validation du champ Carte : Pour un message Product
avec une carte des quantités d'articles, nous pouvons nous assurer que toutes les quantités sont positives.
syntax = "proto3" ;
import "buf/validate/validate.proto" ;
message Product {
// Map of item quantities, all quantities must be positive.
map < string , int32 > item_quantities = 1 [ (buf.validate .field ) .map.values.int32 .gt = 0 ];
}
Validation de type bien connu (WKT) : pour le message User
, nous pouvons ajouter une contrainte pour garantir que l'horodatage created_at
est dans le passé.
syntax = "proto3" ;
import "google/protobuf/timestamp.proto" ;
import "buf/validate/validate.proto" ;
message User {
// User's creation date must be in the past.
google.protobuf.Timestamp created_at = 1 [ (buf.validate .field ) .timestamp .lt_now = true ];
}
Pour des contraintes plus avancées ou personnalisées, protovalidate
autorise les expressions CEL qui peuvent incorporer des informations dans plusieurs champs.
Expressions au niveau du champ : nous pouvons imposer que le price
d'un produit, envoyé sous forme de chaîne, inclut un symbole monétaire tel que "$" ou "£". Nous voulons nous assurer que le prix est positif et que le symbole monétaire est valide.
syntax = "proto3" ;
import "buf/validate/validate.proto" ;
message Product {
string price = 1 [ (buf.validate .field ).cel = {
id : "product.price" ,
message : "Price must be positive and include a valid currency symbol ($ or £)" ,
expression : "(this.startsWith('$') || this.startsWith('£')) && double(this.substring(1)) > 0"
}];
}
Expressions au niveau du message : pour un message Transaction
, nous pouvons utiliser une expression CEL au niveau du message pour garantir que la delivery_date
est toujours après la purchase_date
.
syntax = "proto3" ;
import "google/protobuf/timestamp.proto" ;
import "buf/validate/validate.proto" ;
message Transaction {
google.protobuf.Timestamp purchase_date = 1 ;
google.protobuf.Timestamp delivery_date = 2 ;
option (buf.validate .message ).cel = {
id : "transaction.delivery_date" ,
message : "Delivery date must be after purchase date" ,
expression : "this.delivery_date > this.purchase_date"
};
}
Produire un message d'erreur dans l'expression : Nous pouvons produire des messages d'erreur personnalisés directement dans les expressions CEL. Dans cet exemple, si l' age
est inférieur à 18 ans, l'expression CEL donnera la chaîne de message d'erreur.
syntax = "proto3" ;
import "buf/validate/validate.proto" ;
message User {
int32 age = 1 [ (buf.validate .field ).cel = {
id : "user.age" ,
expression : "this < 18 ? 'User must be at least 18 years old': ''"
}];
}
Consultez examples
pour obtenir des exemples sur les contraintes standard et les contraintes CEL personnalisées.
Une fois les messages annotés avec des contraintes, utilisez l'une des bibliothèques de langage supportées pour valider ; aucune génération de code supplémentaire n'est nécessaire.
protovalidate
fournit un cadre robuste pour valider les messages Protobuf en appliquant des contraintes standard et personnalisées sur divers types de données et en offrant des informations détaillées sur les erreurs lorsque des violations de validation se produisent. Pour un aperçu détaillé de tous ses composants, des contraintes prises en charge et de la manière de les utiliser efficacement, veuillez vous référer à notre documentation complète. Les composants clés comprennent :
Contraintes standard : protovalidate
prend en charge un large éventail de contraintes standard pour tous les types de champs ainsi que des fonctionnalités spéciales pour les types connus de Protobuf. Vous pouvez appliquer ces contraintes à vos messages Protobuf pour vous assurer qu'ils répondent à certaines conditions courantes.
Contraintes personnalisées : avec le Common Expression Language (CEL) de Google, protovalidate
vous permet de créer des contraintes complexes et personnalisées pour gérer des scénarios de validation uniques qui ne sont pas couverts par les contraintes standard au niveau du champ et du message.
Gestion des erreurs : lorsqu'une violation se produit, protovalidate
fournit des informations détaillées sur l'erreur pour vous aider à identifier rapidement la source et à résoudre un problème.
protovalidate
est le successeur spirituel de protoc-gen-validate
, offrant toutes les mêmes fonctionnalités présentes dans le plugin d'origine, sans avoir besoin de génération de code personnalisé, et la nouvelle capacité de décrire des contraintes complexes dans CEL.
Les contraintes de protovalidate
imitent très étroitement celles de protoc-gen-validate
pour garantir une transition facile pour les développeurs. Pour migrer de protoc-gen-validate
vers protovalidate
, utilisez l'outil de migration fourni pour mettre à niveau progressivement vos fichiers .proto
.
Proposé sous licence Apache 2.