prost icon indicating copy to clipboard operation
prost copied to clipboard

Implementing validation for prost -generated structs

Open blaind opened this issue 5 years ago • 5 comments
trafficstars

This is not a bug report or feature request, but rather a question about practical approaches for implementing validation for prost -generated structs (as a part of tonic grpc service).

Use case: I'd like to validate the user-submitted struct data on the server side (e.g. matches regexp, max length, etc.).

Possible ways to resolve this:

1. Create a new trait & implement it on structs

trait MyValidator {
  fn validate() -> bool;
}

impl MyValidator for MyProstStruct {
  fn validate(&self) -> bool {
    if !self.email.contains("@") {
      return false;
    }
    // ... etc
    true
  }
}

2. Use existing validation framework with derive-macros

For example, https://crates.io/crates/validator. The syntax for validator is:

#[derive(Debug, Validate, Deserialize)]
struct SignupData {
    #[validate(email)]
    mail: String
}

this brings a problem, how to actually have prost generate the required macro-markup per struct field. There is config.field_attribute(...) (https://docs.rs/prost-build/0.6.1/prost_build/struct.Config.html#method.field_attribute), but having the actual .proto files and the validation-derives separated in multiple files is hard to manage. Do .proto files have some way to supply metadata per field?

I looked for other alternative frameworks, but could not find one with moderate+ adoption rate.

3. Use existing validation framework without macros

Validator seems to support this, partly, but for example regex validation is missing.

Conclusion

Any ideas, how to proceed with this?

blaind avatar May 26 '20 17:05 blaind

I'm not aware of any widely used 'semantic' validation tools that are used across languages for protobuf. That being said it's been a pain point I've felt in any moderately complex system using protobufs, so I'm certainly open to ideas.

danburkert avatar Nov 15 '20 20:11 danburkert

One could use custom field options to define the validation for a field. For example, one could have a a very generic custom field option like prost_field_attribute that would translate to the equivalent of calling field_attribute on that field.

Example:

message Foo {
  string bar = 1 [(prost_field_attribute) = "#[validate(email)]"];
}

If custom field options get more support, one could perhaps build a more sophisticated companion library prost-validate.

Palmik avatar Dec 06 '20 13:12 Palmik

I think it'd have to work at the Message level, since quite often you also want to do cross field validations, i.e. 'the sum of fields a and b must be even'

danburkert avatar Dec 31 '20 21:12 danburkert

There seems to be a standard developing around https://github.com/envoyproxy/protoc-gen-validate

volfco avatar Jul 13 '21 15:07 volfco

There seems to be a standard developing around https://github.com/envoyproxy/protoc-gen-validate

But it does not have any rust code generator. Why not use this rust validator? https://github.com/KaiserKarel/prosit

makorne avatar Jul 20 '21 04:07 makorne