Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protobuf3: String validation with regex

I have been using Protobuf3 to define a PB message:

syntax = "proto3";
package vioozer_protobuf;

message Update
{
  string sensor_id = 1;
  ...
}

In my system, sensors have a unique id format (a-la SENSOR-1342r43) that can easily be validated with a regex.

Is there a way to add a regex validator to a protobuf field, so that only strings that adhere to the regex would be accepted into that field?

like image 647
Adam Matan Avatar asked Oct 05 '16 11:10

Adam Matan


People also ask

What is oneof in Protobuf?

Protocol Buffer (Protobuf) provides two simpler options for dealing with values that might be of more than one type. The Any type can represent any known Protobuf message type. And you can use the oneof keyword to specify that only one of a range of fields can be set in any message.

What is .proto file?

A . proto file is similar to a JSON file in that it represents structured data, but you can run a compiler on the . proto file to generate code that can read and write the data in the programming language of your choice. For more information about protocol buffers, see Protocol Buffer Developer Guide on Google's site.


2 Answers

Protobuf does not support message validation out of the box, but it is possible to add it using plugin (that's the only way, however, it is not simple).

You can try to find existing plugin, or create your own (if there is no existing plugin for your language).

If you decide to write your own plugin, then first step is to define a custom option for fields:

package yourcompany;

import "google/protobuf/descriptor.proto";

extend google.protobuf.FieldOptions {
    optional string validator = 51234;
}

This option allows you to specify regular expression for a concrete field. Then you apply your new custom option:

message Update {
    string sensor_id = 1 [(yourcompany.validator) = "SENSOR-???????"];
    // ...
}

Second, and more challenging step is to write your own plugin in order to add validation logic to generated code:

Additionally, plugins are able to insert code into the files generated by other code generators. See the comments about "insertion points" in plugin.proto for more on this. This could be used, for example, to write a plugin which generates RPC service code that is tailored for a particular RPC system. See the documentation for the generated code in each language to find out what insertion points they provide.

Your plugin must check value of your custom option and generate additional validation code for fields.

like image 151
Kostiantyn Avatar answered Oct 18 '22 20:10

Kostiantyn


Please check this project protoc-gen-validate https://github.com/envoyproxy/protoc-gen-validate

I wrote an example for Golang here https://github.com/alexcpn/golang_grpc_test

With this you can give semantic validation as a annotation in proto and get it autogenerated as part of protobuff generation

message SearchRequest {
  string query = 1 [(validate.rules).string = {
                      pattern:   "([A-Za-z]+) ([A-Za-z]+)*$",
                      max_bytes: 50,
                   }];
  string email_id= 2 [(validate.rules).string.email = true];
  int32 page_number = 3;  // Which page number do we want?
  int32 result_per_page = 4;  // Number of results to return per page.
}

Server validation using generated stub

func (s *Server)Search(ctx context.Context, in *pb.SearchRequest) (*pb.SearchResponse, error){
    log.Printf("Received Emailid: %v", in.EmailId)
    log.Printf("Received Query: %v", in.Query)

    // Note this is the only place we use validate
    err := in.Validate()
    if err != nil {
        log.Warn("SearchRequest validation failed: %v", err)
like image 31
Alex Punnen Avatar answered Oct 18 '22 20:10

Alex Punnen