Skip to content

Commit aa5c56c

Browse files
feat: extend protobuf schema with more fields and protovalidate validation constraints
1 parent d043495 commit aa5c56c

File tree

5 files changed

+124
-23
lines changed

5 files changed

+124
-23
lines changed

README.md

+15-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ This demo is about to demonstrate how to use protobuf and protovalidate with RES
44

55
## Requirements
66

7-
To generate the go files for the protobuf definitions you need `buf`.
7+
To generate the go files for the protobuf definitions you need `buf` installed.
88

99
## Usage
1010

1111
### Protobuf
1212

13-
To generate the go files for the protobuf definitions run:
13+
To generate the go files to `pkg/proto/demo/v1` for the protobuf definitions located under `proto/demo/v1` run:
1414

1515
```shell
1616
buf generate
@@ -29,5 +29,17 @@ go run cmd/server/main.go
2929
Then request the server with:
3030

3131
```shell
32-
curl localhost:8080/customer
32+
curl -XPOST --json '{}' localhost:8080/customer
33+
```
34+
35+
## Routes
36+
37+
The following CRUD routes are available:
38+
39+
```shell
40+
GET localhost:8080/customer
41+
POST localhost:8080/customer
42+
GET localhost:8080/customer/{id}
43+
PUT localhost:8080/customer/{id}
44+
DELETE localhost:8080/customer/{id}
3345
```

cmd/server/main.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package main
22

33
import (
4-
"github.com/arkadiusjonczek/go-rest-api-protobuf-protovalidate-demo.git/internal/pkg/app"
5-
v1 "github.com/arkadiusjonczek/go-rest-api-protobuf-protovalidate-demo.git/pkg/proto/demo/v1"
6-
"github.com/bufbuild/protovalidate-go"
74
"log"
85
"net/http"
6+
7+
"github.com/bufbuild/protovalidate-go"
8+
9+
"github.com/arkadiusjonczek/go-rest-api-protobuf-protovalidate-demo.git/internal/pkg/app"
10+
v1 "github.com/arkadiusjonczek/go-rest-api-protobuf-protovalidate-demo.git/pkg/proto/demo/v1"
911
)
1012

1113
const (

internal/pkg/app/decoder.go

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ type Decoder[E Entity] interface {
1313

1414
var _ Decoder[v1.Customer] = (*CustomerDecoder)(nil)
1515

16+
// CustomerDecoder is a conrete implementation which doesn't use generics
17+
// because protojson and protovalidate has problems with generics
1618
type CustomerDecoder struct {
1719
unmarshalOptions *protojson.UnmarshalOptions
1820
protovalidate *protovalidate.Validator

pkg/proto/demo/v1/customer.pb.go

+68-16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/demo/v1/customer.proto

+34-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@ option go_package = "demo/v1";
77
import "buf/validate/validate.proto";
88

99
message Customer {
10+
option (buf.validate.message).cel = {
11+
id: "age_required",
12+
message: "age has to be set",
13+
expression: "has(this.age)"
14+
};
15+
16+
option (buf.validate.message).cel = {
17+
id: "age_max",
18+
message: "age has to be gt 0 and lt 120",
19+
expression: "this.age > 0 && this.age < 120"
20+
};
21+
1022
string name = 1 [
1123
(buf.validate.field).required = true,
1224
(buf.validate.field).string = {
@@ -15,5 +27,26 @@ message Customer {
1527
}
1628
];
1729

18-
string test_name = 2;
30+
string username = 2 [
31+
(buf.validate.field).cel = {
32+
id: "username_format",
33+
message: "username must be 3 - 16 characters long and only contain letters and digits",
34+
// `this.matches` match the string against a regex pattern, and evaluates to a bool.
35+
expression: "this.matches('^[A-Za-z0-9]{3,16}$')"
36+
}
37+
];
38+
39+
string email = 3 [
40+
(buf.validate.field).cel = {
41+
id: "valid_email",
42+
message: "email must be a valid email",
43+
expression: "this.isEmail()"
44+
}
45+
];
46+
47+
uint32 age = 4;
48+
49+
string agree = 5 [
50+
(buf.validate.field).string.const = "I agree to the terms and conditions."
51+
];
1952
}

0 commit comments

Comments
 (0)