简体   繁体   中英

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?

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.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM