• Stars
    star
    268
  • Rank 153,144 (Top 4 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 1 year ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Protocol Buffer Validation for Go

The Buf logo protovalidate-go

CI Conformance Report Card GoDoc BSR

protovalidate-go is the Go language implementation of protovalidate designed to validate Protobuf messages at runtime based on user-defined validation constraints. Powered by Google's Common Expression Language (CEL), it provides a flexible and efficient foundation for defining and evaluating custom validation rules. The primary goal of protovalidate is to help developers ensure data consistency and integrity across the network without requiring generated code.

The protovalidate project

Head over to the core protovalidate repository for:

Other protovalidate runtime implementations:

And others coming soon:

  • TypeScript: protovalidate-ts

Installation

Requires the go toolchain (≥ v1.18)

To install the package, use the go get command from within your Go module:

go get github.com/bufbuild/protovalidate-go

Import the package into your Go project:

import "github.com/bufbuild/protovalidate-go"

Remember to always check for the latest version of protovalidate-go on the project's GitHub releases page to ensure you're using the most up-to-date version.

Usage

Implementing validation constraints

Validation constraints are defined directly within .proto files. Documentation for adding constraints can be found in the protovalidate project README and its comprehensive docs.

syntax = "proto3";

package my.package;

import "google/protobuf/timestamp.proto";
import "buf/validate/validate.proto";

message Transaction {
  uint64 id = 1 [(buf.validate.field).uint64.gt = 999];
  google.protobuf.Timestamp purchase_date = 2;
  google.protobuf.Timestamp delivery_date = 3;
  
  string price = 4 [(buf.validate.field).cel = {
    id: "transaction.price",
    message: "price must be positive and include a valid currency symbol ($ or £)",
    expression: "(this.startsWith('$') || this.startsWith('£')) && double(this.substring(1)) > 0"
  }];

  option (buf.validate.message).cel = {
    id: "transaction.delivery_date",
    message: "delivery date must be after purchase date",
    expression: "this.delivery_date > this.purchase_date"
  };
}

Buf managed mode

protovalidate-go assumes the constraint extensions are imported into the generated code via buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go.

If you are using Buf managed mode to augment Go code generation, ensure that the protovalidate module is excluded in your buf.gen.yaml:

version: v1
# <snip>
managed:
  enabled: true
  go_package_prefix:
    except:
      - buf.build/bufbuild/protovalidate
# <snip>

Example

package main

import (
	"fmt"
	"time"
	
	pb "github.com/path/to/generated/protos"
	"github.com/bufbuild/protovalidate-go"
	"google.golang.org/protobuf/types/known/timestamppb"
)

func main() {
	msg := &pb.Transaction{
		Id:           1234,
		Price:        "$5.67",
		PurchaseDate: timestamppb.New(time.Now()),
		DeliveryDate: timestamppb.New(time.Now().Add(time.Hour)),
	}

	v, err := protovalidate.New()
	if err != nil {
		fmt.Println("failed to initialize validator:", err)
	}

	if err = v.Validate(msg); err != nil {
		fmt.Println("validation failed:", err)
	} else {
		fmt.Println("validation succeeded")
	}
}

Lazy mode

protovalidate-go defaults to lazily construct validation logic for Protobuf message types the first time they are encountered. A validator's internal cache can be pre-warmed with the WithMessages or WithDescriptors options during initialization:

validator, err := protovalidate.New(
  protovalidate.WithMessages(
    &pb.MyFoo{}, 
    &pb.MyBar{}, 
  ),
)

Lazy mode uses a copy on write cache stategy to reduce the required locking. While performance is sub-microsecond, the overhead can be further reduced by disabling lazy mode with the WithDisableLazy option. Note that all expected messages must be provided during initialization of the validator:

validator, err := protovalidate.New(
  protovalidate.WithDisableLazy(true),
  protovalidate.WithMessages(
    &pb.MyFoo{},
    &pb.MyBar{},
  ),
)

Support legacy protoc-gen-validate constraints

The protovalidate-go module comes with a legacy package which adds opt-in support for existing protoc-gen-validate constraints. Provide thelegacy.WithLegacySupport option when initializing the validator:

validator, err := protovalidate.New(
  legacy.WithLegacySupport(legacy.ModeMerge),
)

protoc-gen-validate code generation is not used by protovalidate-go. The legacy package assumes the protoc-gen-validate extensions are imported into the generated code via github.com/envoyproxy/protoc-gen-validate/validate.

A migration tool is also available to incrementally upgrade legacy constraints in .proto files.

Performance

Benchmarks are provided to test a variety of use-cases. Generally, after the initial cold start, validation on a message is sub-microsecond and only allocates in the event of a validation error.

[circa 14 September 2023]
goos: darwin
goarch: arm64
pkg: github.com/bufbuild/protovalidate-go
BenchmarkValidator
BenchmarkValidator/ColdStart-10              4192  246278 ns/op  437698 B/op  5955 allocs/op
BenchmarkValidator/Lazy/Valid-10         11816635   95.08 ns/op       0 B/op     0 allocs/op
BenchmarkValidator/Lazy/Invalid-10        2983478   380.5 ns/op     649 B/op    15 allocs/op
BenchmarkValidator/Lazy/FailFast-10      12268683   98.22 ns/op     168 B/op     3 allocs/op
BenchmarkValidator/PreWarmed/Valid-10    12209587   90.36 ns/op       0 B/op     0 allocs/op
BenchmarkValidator/PreWarmed/Invalid-10   3098940   394.1 ns/op     649 B/op    15 allocs/op
BenchmarkValidator/PreWarmed/FailFast-10 12291523   99.27 ns/op     168 B/op     3 allocs/op
PASS

Ecosystem

Offered under the Apache 2 license.

More Repositories

1

buf

The best way of working with Protocol Buffers.
Go
8,960
star
2

protoc-gen-validate

Protocol Buffer Validation - Being replaced by github.com/bufbuild/protovalidate
Go
3,764
star
3

protobuf-es

Protocol Buffers for ECMAScript. The only JavaScript Protobuf library that is fully-compliant with Protobuf conformance tests.
TypeScript
1,114
star
4

connect-es

Connect, gRPC, and gRPC-Web support for Protobuf and TypeScript.
TypeScript
980
star
5

protovalidate

Protocol Buffer Validation - Go, Java, Python, and C++ Beta Releases!
Go
876
star
6

protocompile

A parsing/linking engine for protobuf; the guts for a pure Go replacement of protoc.
Go
228
star
7

knit

GraphQL-like capabilities to services using Protocol Buffers, gRPC, and Connect
Go
148
star
8

buf-language-server

Archived: LSP support is being built into the Buf CLI
Go
126
star
9

connect-query

TypeScript-first expansion pack for TanStack Query that gives you Protobuf superpowers
TypeScript
109
star
10

makego

Makefile setup for our Golang projects.
Makefile
100
star
11

connect-opentelemetry-go

OpenTelemetry tracing and metrics for Connect
Go
81
star
12

buf-examples

Example repository that uses Buf.
C#
73
star
13

connect-es-integration

Examples for using Connect with various TypeScript web frameworks and tooling
TypeScript
71
star
14

connect-demo

An example service built with Connect.
Go
66
star
15

vscode-buf

Visual Studio Code integration for Buf.
TypeScript
60
star
16

knit-go

Knit standalone gateway and Go embeddable gateway
Go
49
star
17

plugins

Remote Protobuf plugins available on the BSR
Dockerfile
49
star
18

connect-swift

Idiomatic gRPC & Connect RPCs for Swift.
Swift
48
star
19

buf-gradle-plugin

Gradle plugin for the Buf CLI
Kotlin
48
star
20

buf-tour

Go
48
star
21

rules_buf

Bazel rules for Buf.
Starlark
47
star
22

protoyaml-go

Marshal and unmarshal Protobuf as YAML with rich error messages.
Go
47
star
23

httplb

Client-side load balancing for net/http
Go
46
star
24

prototransform

Client library for Buf Reflection API, for transforming Protobuf data.
Go
45
star
25

connect-kotlin

Idiomatic gRPC & Connect RPCs for Kotlin.
Kotlin
42
star
26

buf-setup-action

TypeScript
40
star
27

connect-grpcreflect-go

gRPC-compatible server reflection for any net/http server.
Go
39
star
28

protovalidate-java

Protocol Buffer Validation for Java.
Java
37
star
29

protovalidate-python

Protocol Buffer Validation for Python.
Python
37
star
30

vim-buf

Vim integration for Buf.
Vim Script
35
star
31

connect-grpchealth-go

gRPC-compatible health checks for any net/http server.
Go
32
star
32

protoplugin

The missing library to write protoc plugins.
Go
29
star
33

buf-lint-action

TypeScript
28
star
34

buf-breaking-action

TypeScript
26
star
35

knit-ts

TypeScript client for Knit
TypeScript
25
star
36

protobuf.com

Buf's Guide to Protobuf. Home of the language spec and grammar for the Protobuf IDL.
CSS
25
star
37

connect-crosstest

Connect's gRPC and gRPC-Web interoperability test suite.
C++
23
star
38

protobuf-conformance

A repository running the Protobuf conformance tests against various libraries
TypeScript
23
star
39

modules

Collection of third-party modules managed and synced by Buf.
Go
20
star
40

bufstream-demo

A demo of Bufstream, a drop-in replacement for Apache Kafka that's 10x less expensive to operate
Go
20
star
41

protoschema-plugins

Protobuf plugins that generate various schemas from protobuf files - JSON Schema, PubSub, etc.
Go
20
star
42

registry-proto

BSR's new public API. Currently in development.
Makefile
18
star
43

intellij-buf

IntelliJ plugin for Buf
Kotlin
18
star
44

protovalidate-cc

Protocol Buffer Validation for C++.
C++
15
star
45

buf-push-action

Shell
15
star
46

buf-action

Build, format, lint, and check for breaking changes in your Protobuf schemas, and automatically publish to the Buf Schema Registry.
TypeScript
15
star
47

bufplugin-go

The Go library for plugins to the Buf platform.
Go
13
star
48

homebrew-buf

Homebrew tap for Buf.
Shell
12
star
49

docs.buf.build

The source for https://docs.buf.build.
TypeScript
11
star
50

tree-sitter-cel

Tree sitter grammar for the Common Expression Language (CEL)
C
10
star
51

wellknowntypes

All the Well-Known Types stored in per-version directories.
Go
9
star
52

connect-envoy-demo

Demonstration of how to use the new Connect-gRPC Envoy filter, available in Envoy v1.26+.
Go
8
star
53

knit-proto

Protocol definition for Knit
7
star
54

reflect-proto

Protobuf reflection API.
7
star
55

bufisk

Bazelisk, but for Buf. A user-friendly launcher for Buf.
Go
7
star
56

knit-demo

An example service built with Knit
Go
6
star
57

protobuf-language-spec

Comprehensive language specification for Protocol Buffers
6
star
58

tools

A collection of tools written at Buf.
JavaScript
5
star
59

confluent-proto

Proto definitions for integrating Confluent Schema Registry with the BSR
Makefile
4
star
60

jest-environment-jsdom

A modern jsdom test environment for Jest
TypeScript
4
star
61

base-workflows

Shared Github Actions for BufBuild Organization.
3
star
62

spdx-go

A simple Golang library that contains license information from SPDX.
Go
2
star
63

bufplugin

The APIs for plugins to the Buf platform.
Makefile
2
star
64

.github

1
star