├── .bazelversion ├── chapter2 ├── account.txt ├── fixed.txt ├── sfixed.txt ├── floating_point.txt ├── length-delimited.txt ├── repeated.txt ├── account.proto ├── README.md └── wrappers.proto ├── chapter3 ├── .gitignore ├── accounts.bin.gz ├── accounts.json.gz ├── go.mod ├── proto │ ├── accounts.proto │ ├── account.proto │ └── BUILD.bazel ├── BUILD.bazel ├── go.sum ├── README.md └── main.go ├── chapter4 ├── .bazelversion ├── .bazelrc ├── go.work ├── buf.yaml ├── buf.gen.yaml ├── proto │ ├── dummy │ │ └── v1 │ │ │ ├── dummy.proto │ │ │ └── BUILD.bazel │ ├── go.mod │ └── go.sum ├── client │ ├── go.mod │ ├── BUILD.bazel │ ├── main.go │ └── go.sum ├── server │ ├── go.mod │ ├── BUILD.bazel │ ├── main.go │ └── go.sum ├── BUILD.bazel ├── README.md └── versions.bzl ├── chapter5 ├── .bazelversion ├── .bazelrc ├── go.work ├── buf.yaml ├── buf.gen.yaml ├── server │ ├── server.go │ ├── db.go │ ├── go.mod │ ├── BUILD.bazel │ ├── main.go │ ├── go.sum │ ├── impl.go │ └── in_memory.go ├── proto │ ├── go.mod │ ├── todo │ │ └── v1 │ │ │ ├── BUILD.bazel │ │ │ └── todo.proto │ └── go.sum ├── BUILD.bazel ├── client │ ├── go.mod │ ├── BUILD.bazel │ └── go.sum ├── README.md └── versions.bzl ├── chapter6 ├── .bazelversion ├── .bazelrc ├── go.work ├── buf.yaml ├── buf.gen.yaml ├── server │ ├── server.go │ ├── db.go │ ├── go.mod │ ├── main.go │ ├── BUILD.bazel │ ├── go.sum │ └── in_memory.go ├── proto │ ├── go.mod │ ├── todo │ │ ├── v1 │ │ │ ├── BUILD.bazel │ │ │ └── todo.proto │ │ └── v2 │ │ │ ├── BUILD.bazel │ │ │ └── todo.proto │ └── go.sum ├── BUILD.bazel ├── client │ ├── go.mod │ ├── BUILD.bazel │ └── go.sum ├── README.md └── versions.bzl ├── chapter7 ├── .bazelversion ├── .bazelrc ├── go.work ├── buf.yaml ├── certs │ ├── BUILD.bazel │ ├── README.md │ ├── server_cert.pem │ └── ca_cert.pem ├── k8s │ ├── kind.yaml │ ├── client.yaml │ └── server.yaml ├── buf.gen.yaml ├── server │ ├── server.go │ ├── db.go │ ├── go.mod │ ├── BUILD.bazel │ ├── main.go │ ├── go.sum │ ├── in_memory.go │ └── interceptors.go ├── proto │ ├── go.mod │ ├── todo │ │ ├── v1 │ │ │ ├── BUILD.bazel │ │ │ └── todo.proto │ │ └── v2 │ │ │ ├── BUILD.bazel │ │ │ └── todo.proto │ └── go.sum ├── BUILD.bazel ├── client │ ├── go.mod │ ├── BUILD.bazel │ ├── interceptors.go │ └── go.sum ├── versions.bzl └── README.md ├── chapter8 ├── .bazelversion ├── .bazelrc ├── go.work ├── certs │ ├── BUILD.bazel │ ├── README.md │ ├── server_cert.pem │ └── ca_cert.pem ├── k8s │ ├── kind.yaml │ ├── client.yaml │ └── server.yaml ├── buf.yaml ├── server │ ├── server.go │ ├── db.go │ ├── limit.go │ ├── go.mod │ ├── BUILD.bazel │ ├── interceptors.go │ └── in_memory.go ├── buf.gen.yaml ├── BUILD.bazel ├── proto │ ├── go.mod │ ├── validate │ │ └── BUILD.bazel │ ├── todo │ │ ├── v1 │ │ │ ├── BUILD.bazel │ │ │ └── todo.proto │ │ └── v2 │ │ │ ├── BUILD.bazel │ │ │ └── todo.proto │ └── go.sum ├── client │ ├── go.mod │ ├── BUILD.bazel │ ├── interceptors.go │ └── go.sum ├── versions.bzl └── README.md ├── chapter9 ├── .bazelversion ├── .bazelrc ├── go.work ├── certs │ ├── BUILD.bazel │ ├── README.md │ ├── server_cert.pem │ └── ca_cert.pem ├── k8s │ ├── kind.yaml │ ├── client.yaml │ └── server.yaml ├── buf.yaml ├── envoy │ ├── service.yaml │ ├── Dockerfile │ ├── deployment.yaml │ └── envoy.yaml ├── server │ ├── server.go │ ├── db.go │ ├── limit.go │ ├── test_options.go │ ├── server_test.go │ ├── go.mod │ ├── fake_db.go │ ├── interceptors.go │ └── in_memory.go ├── buf.gen.yaml ├── BUILD.bazel ├── proto │ ├── go.mod │ ├── todo │ │ ├── v1 │ │ │ ├── BUILD.bazel │ │ │ └── todo.proto │ │ └── v2 │ │ │ ├── BUILD.bazel │ │ │ └── todo.proto │ ├── validate │ │ └── BUILD.bazel │ └── go.sum ├── client │ ├── go.mod │ ├── interceptors.go │ ├── BUILD.bazel │ └── go.sum ├── versions.bzl ├── README.md └── WORKSPACE.bazel ├── .bazelrc ├── .gitignore ├── scripts ├── constants.sh ├── README.md ├── cleanall.sh ├── dockerbuild.sh └── updateall.sh ├── .gitattributes ├── certs ├── BUILD.bazel ├── README.md ├── server_cert.pem └── ca_cert.pem ├── chapter1 ├── Unary.pcapng ├── Bidi Streaming.pcapng ├── Client Streaming.pcapng ├── Server Streaming.pcapng └── README.md ├── go.work ├── helpers ├── go.mod ├── proto │ ├── split.proto │ ├── tags.proto │ └── todo.proto ├── go.sum ├── split.go ├── tags.go ├── integers.go ├── README.md └── gzip.go ├── .vscode └── settings.json ├── proto ├── go.mod ├── todo │ ├── v1 │ │ ├── BUILD.bazel │ │ └── todo.proto │ └── v2 │ │ ├── BUILD.bazel │ │ └── todo.proto ├── validate │ └── BUILD.bazel └── go.sum ├── Makefile ├── BUILD.bazel ├── LICENSE ├── go.work.sum ├── versions.bzl └── WORKSPACE.bazel /.bazelversion: -------------------------------------------------------------------------------- 1 | 6.4.0 -------------------------------------------------------------------------------- /chapter2/account.txt: -------------------------------------------------------------------------------- 1 | id: 123 -------------------------------------------------------------------------------- /chapter2/fixed.txt: -------------------------------------------------------------------------------- 1 | value: 42 -------------------------------------------------------------------------------- /chapter3/.gitignore: -------------------------------------------------------------------------------- 1 | *.pb.go -------------------------------------------------------------------------------- /chapter4/.bazelversion: -------------------------------------------------------------------------------- 1 | 6.2.1 -------------------------------------------------------------------------------- /chapter5/.bazelversion: -------------------------------------------------------------------------------- 1 | 6.2.1 -------------------------------------------------------------------------------- /chapter6/.bazelversion: -------------------------------------------------------------------------------- 1 | 6.2.1 -------------------------------------------------------------------------------- /chapter7/.bazelversion: -------------------------------------------------------------------------------- 1 | 6.2.1 -------------------------------------------------------------------------------- /chapter8/.bazelversion: -------------------------------------------------------------------------------- 1 | 6.2.1 -------------------------------------------------------------------------------- /chapter9/.bazelversion: -------------------------------------------------------------------------------- 1 | 6.2.1 -------------------------------------------------------------------------------- /chapter2/sfixed.txt: -------------------------------------------------------------------------------- 1 | value: -42 -------------------------------------------------------------------------------- /chapter2/floating_point.txt: -------------------------------------------------------------------------------- 1 | value: 42.42 -------------------------------------------------------------------------------- /chapter2/length-delimited.txt: -------------------------------------------------------------------------------- 1 | value: "0123456789" 2 | -------------------------------------------------------------------------------- /.bazelrc: -------------------------------------------------------------------------------- 1 | build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/bazel-* 2 | **/*.pb.go 3 | **/*.pb.validate.go -------------------------------------------------------------------------------- /chapter4/.bazelrc: -------------------------------------------------------------------------------- 1 | build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 -------------------------------------------------------------------------------- /chapter5/.bazelrc: -------------------------------------------------------------------------------- 1 | build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 -------------------------------------------------------------------------------- /chapter6/.bazelrc: -------------------------------------------------------------------------------- 1 | build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 -------------------------------------------------------------------------------- /chapter7/.bazelrc: -------------------------------------------------------------------------------- 1 | build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 -------------------------------------------------------------------------------- /chapter8/.bazelrc: -------------------------------------------------------------------------------- 1 | build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 -------------------------------------------------------------------------------- /chapter9/.bazelrc: -------------------------------------------------------------------------------- 1 | build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 -------------------------------------------------------------------------------- /scripts/constants.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CHAPTERS_NB="4 5 6 7 8 9" -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bazel linguist-detectable=false 2 | *.bzl linguist-detectable=false -------------------------------------------------------------------------------- /chapter4/go.work: -------------------------------------------------------------------------------- 1 | go 1.22 2 | 3 | use ( 4 | ./client 5 | ./proto 6 | ./server 7 | ) 8 | -------------------------------------------------------------------------------- /chapter5/go.work: -------------------------------------------------------------------------------- 1 | go 1.22 2 | 3 | use ( 4 | ./client 5 | ./proto 6 | ./server 7 | ) 8 | -------------------------------------------------------------------------------- /chapter6/go.work: -------------------------------------------------------------------------------- 1 | go 1.22 2 | 3 | use ( 4 | ./client 5 | ./proto 6 | ./server 7 | ) 8 | -------------------------------------------------------------------------------- /chapter7/go.work: -------------------------------------------------------------------------------- 1 | go 1.22 2 | 3 | use ( 4 | ./client 5 | ./proto 6 | ./server 7 | ) 8 | -------------------------------------------------------------------------------- /chapter8/go.work: -------------------------------------------------------------------------------- 1 | go 1.22 2 | 3 | use ( 4 | ./client 5 | ./proto 6 | ./server 7 | ) 8 | -------------------------------------------------------------------------------- /chapter9/go.work: -------------------------------------------------------------------------------- 1 | go 1.22 2 | 3 | use ( 4 | ./client 5 | ./proto 6 | ./server 7 | ) 8 | -------------------------------------------------------------------------------- /chapter4/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /chapter5/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /chapter6/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /chapter7/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | -------------------------------------------------------------------------------- /certs/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files([ 2 | "server_cert.pem", 3 | "server_key.pem", 4 | "ca_cert.pem", 5 | ]) 6 | -------------------------------------------------------------------------------- /chapter1/Unary.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/gRPC-Go-for-Professionals/HEAD/chapter1/Unary.pcapng -------------------------------------------------------------------------------- /chapter3/accounts.bin.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/gRPC-Go-for-Professionals/HEAD/chapter3/accounts.bin.gz -------------------------------------------------------------------------------- /chapter3/accounts.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/gRPC-Go-for-Professionals/HEAD/chapter3/accounts.json.gz -------------------------------------------------------------------------------- /chapter7/certs/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files([ 2 | "server_cert.pem", 3 | "server_key.pem", 4 | "ca_cert.pem", 5 | ]) 6 | -------------------------------------------------------------------------------- /chapter8/certs/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files([ 2 | "server_cert.pem", 3 | "server_key.pem", 4 | "ca_cert.pem", 5 | ]) 6 | -------------------------------------------------------------------------------- /chapter9/certs/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files([ 2 | "server_cert.pem", 3 | "server_key.pem", 4 | "ca_cert.pem", 5 | ]) 6 | -------------------------------------------------------------------------------- /chapter1/Bidi Streaming.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/gRPC-Go-for-Professionals/HEAD/chapter1/Bidi Streaming.pcapng -------------------------------------------------------------------------------- /chapter1/Client Streaming.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/gRPC-Go-for-Professionals/HEAD/chapter1/Client Streaming.pcapng -------------------------------------------------------------------------------- /chapter1/Server Streaming.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/gRPC-Go-for-Professionals/HEAD/chapter1/Server Streaming.pcapng -------------------------------------------------------------------------------- /chapter7/k8s/kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | - role: worker 6 | - role: worker -------------------------------------------------------------------------------- /chapter8/k8s/kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | - role: worker 6 | - role: worker -------------------------------------------------------------------------------- /chapter9/k8s/kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | - role: worker 6 | - role: worker -------------------------------------------------------------------------------- /chapter2/repeated.txt: -------------------------------------------------------------------------------- 1 | values: 1 2 | values: 2 3 | values: 3 4 | values: 4 5 | values: 5 6 | values: 6 7 | values: 7 8 | values: 8 9 | values: 9 10 | -------------------------------------------------------------------------------- /chapter8/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | deps: 9 | - buf.build/envoyproxy/protoc-gen-validate -------------------------------------------------------------------------------- /chapter9/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | breaking: 3 | use: 4 | - FILE 5 | lint: 6 | use: 7 | - DEFAULT 8 | deps: 9 | - buf.build/envoyproxy/protoc-gen-validate -------------------------------------------------------------------------------- /chapter4/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: proto 5 | opt: paths=source_relative 6 | - plugin: go-grpc 7 | out: proto 8 | opt: paths=source_relative 9 | -------------------------------------------------------------------------------- /chapter5/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: proto 5 | opt: paths=source_relative 6 | - plugin: go-grpc 7 | out: proto 8 | opt: paths=source_relative 9 | -------------------------------------------------------------------------------- /chapter6/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: proto 5 | opt: paths=source_relative 6 | - plugin: go-grpc 7 | out: proto 8 | opt: paths=source_relative 9 | -------------------------------------------------------------------------------- /chapter7/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: proto 5 | opt: paths=source_relative 6 | - plugin: go-grpc 7 | out: proto 8 | opt: paths=source_relative 9 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | # Scripts 2 | 3 | > These scripts are here for maintenance of the project. They are not supposed to be used by readers, however it can show some useful tricks for managing a gRPC project. -------------------------------------------------------------------------------- /chapter3/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3 2 | 3 | go 1.20 4 | 5 | require google.golang.org/protobuf v1.30.0 6 | 7 | require github.com/google/go-cmp v0.5.9 // indirect 8 | -------------------------------------------------------------------------------- /chapter9/envoy/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: todo-envoy 5 | spec: 6 | clusterIP: None 7 | ports: 8 | - name: grpc 9 | port: 50051 10 | selector: 11 | app: todo-envoy 12 | -------------------------------------------------------------------------------- /chapter5/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1" 5 | ) 6 | 7 | type server struct { 8 | d db 9 | 10 | pb.UnimplementedTodoServiceServer 11 | } 12 | -------------------------------------------------------------------------------- /chapter6/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 5 | ) 6 | 7 | type server struct { 8 | d db 9 | 10 | pb.UnimplementedTodoServiceServer 11 | } 12 | -------------------------------------------------------------------------------- /chapter7/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 5 | ) 6 | 7 | type server struct { 8 | d db 9 | 10 | pb.UnimplementedTodoServiceServer 11 | } 12 | -------------------------------------------------------------------------------- /chapter8/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 5 | ) 6 | 7 | type server struct { 8 | d db 9 | 10 | pb.UnimplementedTodoServiceServer 11 | } 12 | -------------------------------------------------------------------------------- /chapter9/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 5 | ) 6 | 7 | type server struct { 8 | d db 9 | 10 | pb.UnimplementedTodoServiceServer 11 | } 12 | -------------------------------------------------------------------------------- /chapter3/proto/accounts.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "account.proto"; 4 | 5 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3/proto"; 6 | 7 | message Accounts { 8 | repeated Account values = 1; 9 | } -------------------------------------------------------------------------------- /chapter4/proto/dummy/v1/dummy.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package dummy.v1; 4 | 5 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/dummy/v1"; 6 | 7 | message DummyMessage {} 8 | 9 | service DummyService {} 10 | -------------------------------------------------------------------------------- /chapter8/k8s/client.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: todo-client 5 | spec: 6 | containers: 7 | - name: todo-client 8 | image: clementjean/packt-book:client 9 | # imagePullPolicy: Always 10 | restartPolicy: Never -------------------------------------------------------------------------------- /chapter7/k8s/client.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: todo-client 5 | spec: 6 | containers: 7 | - name: todo-client 8 | image: clementjean/grpc-go-packt-book:client 9 | # imagePullPolicy: Always 10 | restartPolicy: Never -------------------------------------------------------------------------------- /chapter9/k8s/client.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: todo-client 5 | spec: 6 | containers: 7 | - name: todo-client 8 | image: clementjean/grpc-go-packt-book:client 9 | imagePullPolicy: Always 10 | restartPolicy: Never -------------------------------------------------------------------------------- /go.work: -------------------------------------------------------------------------------- 1 | go 1.22 2 | 3 | toolchain go1.22.1 4 | 5 | // This workspace file is purely for maintenance. 6 | // Please check the workspace file in the chapter folders. 7 | 8 | use ( 9 | ./chapter9/client 10 | ./chapter9/proto 11 | ./chapter9/server 12 | ./helpers 13 | ) 14 | -------------------------------------------------------------------------------- /helpers/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/helpers 2 | 3 | go 1.22 4 | 5 | require ( 6 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 7 | google.golang.org/protobuf v1.33.0 8 | ) 9 | 10 | require github.com/google/go-cmp v0.6.0 // indirect 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[proto3]": { 3 | "editor.detectIndentation": false, 4 | "editor.indentSize": 2, 5 | "editor.insertSpaces": true 6 | }, 7 | "[starlark]": { 8 | "editor.detectIndentation": false, 9 | "editor.indentSize": 4, 10 | "editor.insertSpaces": true 11 | } 12 | } -------------------------------------------------------------------------------- /helpers/proto/split.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/helpers/proto"; 4 | 5 | message ComplexName { 6 | string name = 1; 7 | } 8 | 9 | message Split { 10 | string name = 1; 11 | 12 | ComplexName complex_name = 2; 13 | } -------------------------------------------------------------------------------- /chapter8/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: proto 5 | opt: paths=source_relative 6 | - plugin: go-grpc 7 | out: proto 8 | opt: paths=source_relative 9 | - plugin: buf.build/bufbuild/validate-go 10 | out: proto 11 | opt: paths=source_relative 12 | -------------------------------------------------------------------------------- /chapter9/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: proto 5 | opt: paths=source_relative 6 | - plugin: go-grpc 7 | out: proto 8 | opt: paths=source_relative 9 | - plugin: buf.build/bufbuild/validate-go 10 | out: proto 11 | opt: paths=source_relative 12 | -------------------------------------------------------------------------------- /chapter9/envoy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM envoyproxy/envoy-distroless:v1.26-latest 2 | COPY ./envoy/envoy.yaml /etc/envoy/envoy.yaml 3 | COPY ./certs/server_cert.pem /etc/envoy/certs/server_cert.pem 4 | COPY ./certs/server_key.pem /etc/envoy/certs/server_key.pem 5 | EXPOSE 50051 6 | CMD ["--config-path", "/etc/envoy/envoy.yaml"] -------------------------------------------------------------------------------- /helpers/proto/tags.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/helpers/proto"; 4 | 5 | message Tags { 6 | int32 tag = 1; 7 | int32 tag2 = 16; 8 | int32 tag3 = 2048; 9 | int32 tag4 = 262144; 10 | int32 tag5 = 33554432; 11 | int32 tag6 = 536870911; 12 | } -------------------------------------------------------------------------------- /certs/README.md: -------------------------------------------------------------------------------- 1 | # Certs 2 | 3 | The files in here are copied from the x509 folder in the [grpc-go/examples/data](https://github.com/grpc/grpc-go/tree/master/examples/data/x509) folder in [grpc-go](https://github.com/grpc/grpc-go). This lets us focus on writing gRPC code and not worrying generating these certificates (let the experts handle this). -------------------------------------------------------------------------------- /chapter7/certs/README.md: -------------------------------------------------------------------------------- 1 | # Certs 2 | 3 | The files in here are copied from the x509 folder in the [grpc-go/examples/data](https://github.com/grpc/grpc-go/tree/master/examples/data/x509) folder in [grpc-go](https://github.com/grpc/grpc-go). This lets us focus on writing gRPC code and not worrying generating these certificates (let the experts handle this). -------------------------------------------------------------------------------- /chapter8/certs/README.md: -------------------------------------------------------------------------------- 1 | # Certs 2 | 3 | The files in here are copied from the x509 folder in the [grpc-go/examples/data](https://github.com/grpc/grpc-go/tree/master/examples/data/x509) folder in [grpc-go](https://github.com/grpc/grpc-go). This lets us focus on writing gRPC code and not worrying generating these certificates (let the experts handle this). -------------------------------------------------------------------------------- /chapter9/certs/README.md: -------------------------------------------------------------------------------- 1 | # Certs 2 | 3 | The files in here are copied from the x509 folder in the [grpc-go/examples/data](https://github.com/grpc/grpc-go/tree/master/examples/data/x509) folder in [grpc-go](https://github.com/grpc/grpc-go). This lets us focus on writing gRPC code and not worrying generating these certificates (let the experts handle this). -------------------------------------------------------------------------------- /helpers/proto/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo; 4 | 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/helpers/proto"; 8 | 9 | message Task { 10 | uint64 id = 1; 11 | string description = 2; 12 | bool done = 3; 13 | google.protobuf.Timestamp due_date = 4; 14 | } -------------------------------------------------------------------------------- /chapter2/account.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals"; 4 | 5 | enum AccountRight { 6 | ACCOUNT_RIGHT_UNSPECIFIED = 0; 7 | ACCOUNT_RIGHT_READ = 1; 8 | ACCOUNT_RIGHT_READ_WRITE = 2; 9 | ACCOUNT_RIGHT_ADMIN = 3; 10 | } 11 | 12 | message Account { 13 | uint64 id = 1; 14 | string username = 2; 15 | AccountRight right = 3; 16 | } -------------------------------------------------------------------------------- /chapter5/server/db.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | // db is the interface representing the actions we want to take on any database. 6 | type db interface { 7 | addTask(description string, dueDate time.Time) (uint64, error) 8 | getTasks(f func(interface{}) error) error 9 | updateTask(id uint64, description string, dueDate time.Time, done bool) error 10 | deleteTask(id uint64) error 11 | } 12 | -------------------------------------------------------------------------------- /chapter6/server/db.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | // db is the interface representing the actions we want to take on any database. 6 | type db interface { 7 | addTask(description string, dueDate time.Time) (uint64, error) 8 | getTasks(f func(interface{}) error) error 9 | updateTask(id uint64, description string, dueDate time.Time, done bool) error 10 | deleteTask(id uint64) error 11 | } 12 | -------------------------------------------------------------------------------- /chapter7/server/db.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | // db is the interface representing the actions we want to take on any database. 6 | type db interface { 7 | addTask(description string, dueDate time.Time) (uint64, error) 8 | getTasks(f func(interface{}) error) error 9 | updateTask(id uint64, description string, dueDate time.Time, done bool) error 10 | deleteTask(id uint64) error 11 | } 12 | -------------------------------------------------------------------------------- /chapter8/server/db.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | // db is the interface representing the actions we want to take on any database. 6 | type db interface { 7 | addTask(description string, dueDate time.Time) (uint64, error) 8 | getTasks(f func(interface{}) error) error 9 | updateTask(id uint64, description string, dueDate time.Time, done bool) error 10 | deleteTask(id uint64) error 11 | } 12 | -------------------------------------------------------------------------------- /chapter9/server/db.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | // db is the interface representing the actions we want to take on any database. 6 | type db interface { 7 | addTask(description string, dueDate time.Time) (uint64, error) 8 | getTasks(f func(interface{}) error) error 9 | updateTask(id uint64, description string, dueDate time.Time, done bool) error 10 | deleteTask(id uint64) error 11 | } 12 | -------------------------------------------------------------------------------- /chapter3/proto/account.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3/proto"; 4 | 5 | message Account { 6 | uint64 id = 1; 7 | string username = 2; 8 | } 9 | 10 | message LogoutRequest { 11 | Account account = 1; 12 | } 13 | 14 | message LogoutResponse {} 15 | 16 | service AccountService { 17 | rpc Logout (LogoutRequest) returns (LogoutResponse); 18 | } -------------------------------------------------------------------------------- /chapter4/client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/client 2 | 3 | go 1.22 4 | 5 | require google.golang.org/grpc v1.63.2 6 | 7 | require ( 8 | golang.org/x/net v0.24.0 // indirect 9 | golang.org/x/sys v0.19.0 // indirect 10 | golang.org/x/text v0.14.0 // indirect 11 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 12 | google.golang.org/protobuf v1.33.0 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /chapter4/proto/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/proto 2 | 3 | go 1.20 4 | 5 | require ( 6 | google.golang.org/grpc v1.63.2 7 | google.golang.org/protobuf v1.33.0 8 | ) 9 | 10 | require ( 11 | golang.org/x/net v0.24.0 // indirect 12 | golang.org/x/sys v0.19.0 // indirect 13 | golang.org/x/text v0.14.0 // indirect 14 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /chapter4/server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/server 2 | 3 | go 1.22 4 | 5 | require google.golang.org/grpc v1.63.2 6 | 7 | require ( 8 | golang.org/x/net v0.24.0 // indirect 9 | golang.org/x/sys v0.19.0 // indirect 10 | golang.org/x/text v0.14.0 // indirect 11 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 12 | google.golang.org/protobuf v1.33.0 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /chapter5/proto/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/proto 2 | 3 | go 1.20 4 | 5 | require ( 6 | google.golang.org/grpc v1.63.2 7 | google.golang.org/protobuf v1.33.0 8 | ) 9 | 10 | require ( 11 | golang.org/x/net v0.24.0 // indirect 12 | golang.org/x/sys v0.19.0 // indirect 13 | golang.org/x/text v0.14.0 // indirect 14 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /chapter6/proto/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/proto 2 | 3 | go 1.20 4 | 5 | require ( 6 | google.golang.org/grpc v1.63.2 7 | google.golang.org/protobuf v1.33.0 8 | ) 9 | 10 | require ( 11 | golang.org/x/net v0.24.0 // indirect 12 | golang.org/x/sys v0.19.0 // indirect 13 | golang.org/x/text v0.14.0 // indirect 14 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /chapter7/proto/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/proto 2 | 3 | go 1.20 4 | 5 | require ( 6 | google.golang.org/grpc v1.63.2 7 | google.golang.org/protobuf v1.33.0 8 | ) 9 | 10 | require ( 11 | golang.org/x/net v0.24.0 // indirect 12 | golang.org/x/sys v0.19.0 // indirect 13 | golang.org/x/text v0.14.0 // indirect 14 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /scripts/cleanall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script is for maintenance of the projects. 4 | # It cleans the different folders by removing 5 | # generated code and bazel builds. 6 | 7 | . ./scripts/constants.sh 8 | 9 | pwd=$(pwd) 10 | 11 | for nb in $CHAPTERS_NB 12 | do 13 | if [ -d "$pwd/chapter$nb" ] 14 | then 15 | echo "enter $pwd/chapter$nb" 16 | cd $pwd/chapter$nb 17 | find proto -name "*.pb.go" -type f -exec rm -rf '{}' \; 18 | bazel clean --expunge 19 | fi 20 | done -------------------------------------------------------------------------------- /chapter4/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | 3 | # gazelle:exclude proto/**/*.go 4 | # gazelle:prefix github.com/PacktPublishing/gRPC-Go-for-Professionals 5 | gazelle(name = "gazelle") 6 | 7 | gazelle( 8 | name = "gazelle-update-repos", 9 | args = [ 10 | "-from_file=go.work", 11 | "-to_macro=deps.bzl%go_dependencies", 12 | "-prune", 13 | "-build_file_proto_mode=disable_global", 14 | ], 15 | command = "update-repos", 16 | ) 17 | -------------------------------------------------------------------------------- /chapter5/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | 3 | # gazelle:exclude proto/**/*.go 4 | # gazelle:prefix github.com/PacktPublishing/gRPC-Go-for-Professionals 5 | gazelle(name = "gazelle") 6 | 7 | gazelle( 8 | name = "gazelle-update-repos", 9 | args = [ 10 | "-from_file=go.work", 11 | "-to_macro=deps.bzl%go_dependencies", 12 | "-prune", 13 | "-build_file_proto_mode=disable_global", 14 | ], 15 | command = "update-repos", 16 | ) 17 | -------------------------------------------------------------------------------- /chapter6/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | 3 | # gazelle:exclude proto/**/*.go 4 | # gazelle:prefix github.com/PacktPublishing/gRPC-Go-for-Professionals 5 | gazelle(name = "gazelle") 6 | 7 | gazelle( 8 | name = "gazelle-update-repos", 9 | args = [ 10 | "-from_file=go.work", 11 | "-to_macro=deps.bzl%go_dependencies", 12 | "-prune", 13 | "-build_file_proto_mode=disable_global", 14 | ], 15 | command = "update-repos", 16 | ) 17 | -------------------------------------------------------------------------------- /chapter7/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | 3 | # gazelle:exclude proto/**/*.go 4 | # gazelle:prefix github.com/PacktPublishing/gRPC-Go-for-Professionals 5 | gazelle(name = "gazelle") 6 | 7 | gazelle( 8 | name = "gazelle-update-repos", 9 | args = [ 10 | "-from_file=go.work", 11 | "-to_macro=deps.bzl%go_dependencies", 12 | "-prune", 13 | "-build_file_proto_mode=disable_global", 14 | ], 15 | command = "update-repos", 16 | ) 17 | -------------------------------------------------------------------------------- /chapter8/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | 3 | # gazelle:exclude proto/**/*.go 4 | # gazelle:prefix github.com/PacktPublishing/gRPC-Go-for-Professionals 5 | gazelle(name = "gazelle") 6 | 7 | gazelle( 8 | name = "gazelle-update-repos", 9 | args = [ 10 | "-from_file=go.work", 11 | "-to_macro=deps.bzl%go_dependencies", 12 | "-prune", 13 | "-build_file_proto_mode=disable_global", 14 | ], 15 | command = "update-repos", 16 | ) 17 | -------------------------------------------------------------------------------- /chapter9/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | 3 | # gazelle:exclude proto/**/*.go 4 | # gazelle:prefix github.com/PacktPublishing/gRPC-Go-for-Professionals 5 | gazelle(name = "gazelle") 6 | 7 | gazelle( 8 | name = "gazelle-update-repos", 9 | args = [ 10 | "-from_file=go.work", 11 | "-to_macro=deps.bzl%go_dependencies", 12 | "-prune", 13 | "-build_file_proto_mode=disable_global", 14 | ], 15 | command = "update-repos", 16 | ) 17 | -------------------------------------------------------------------------------- /proto/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/proto 2 | 3 | go 1.22 4 | 5 | require ( 6 | github.com/envoyproxy/protoc-gen-validate v1.0.4 7 | google.golang.org/grpc v1.63.2 8 | google.golang.org/protobuf v1.33.0 9 | ) 10 | 11 | require ( 12 | golang.org/x/net v0.24.0 // indirect 13 | golang.org/x/sys v0.19.0 // indirect 14 | golang.org/x/text v0.14.0 // indirect 15 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /chapter8/proto/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/proto 2 | 3 | go 1.22 4 | 5 | require ( 6 | github.com/envoyproxy/protoc-gen-validate v1.0.4 7 | google.golang.org/grpc v1.63.2 8 | google.golang.org/protobuf v1.33.0 9 | ) 10 | 11 | require ( 12 | golang.org/x/net v0.24.0 // indirect 13 | golang.org/x/sys v0.19.0 // indirect 14 | golang.org/x/text v0.14.0 // indirect 15 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /chapter9/proto/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/proto 2 | 3 | go 1.22 4 | 5 | require ( 6 | github.com/envoyproxy/protoc-gen-validate v1.0.4 7 | google.golang.org/grpc v1.63.2 8 | google.golang.org/protobuf v1.33.0 9 | ) 10 | 11 | require ( 12 | golang.org/x/net v0.24.0 // indirect 13 | golang.org/x/sys v0.19.0 // indirect 14 | golang.org/x/text v0.14.0 // indirect 15 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /chapter9/envoy/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: todo-envoy 5 | labels: 6 | app: todo-envoy 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: todo-envoy 12 | template: 13 | metadata: 14 | labels: 15 | app: todo-envoy 16 | spec: 17 | containers: 18 | - name: todo-envoy 19 | image: clementjean/grpc-go-packt-book:envoy-proxy 20 | imagePullPolicy: Always 21 | ports: 22 | - name: grpc 23 | containerPort: 50051 24 | -------------------------------------------------------------------------------- /helpers/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc= 4 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= 5 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 6 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 7 | -------------------------------------------------------------------------------- /chapter8/server/limit.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "golang.org/x/time/rate" 8 | ) 9 | 10 | // simpleLimiter is a wrapper around a rate.Limiter (Token Bucket Rate Limiter) 11 | type simpleLimiter struct { 12 | limiter *rate.Limiter 13 | } 14 | 15 | // Limit tells wether or not to allow a certain request 16 | // depending on the underlying limiter decision. 17 | func (l *simpleLimiter) Limit(_ context.Context) error { 18 | if !l.limiter.Allow() { 19 | return fmt.Errorf("reached Rate-Limiting %v", l.limiter.Limit()) 20 | } 21 | 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /chapter9/server/limit.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "golang.org/x/time/rate" 8 | ) 9 | 10 | // simpleLimiter is a wrapper around a rate.Limiter (Token Bucket Rate Limiter) 11 | type simpleLimiter struct { 12 | limiter *rate.Limiter 13 | } 14 | 15 | // Limit tells wether or not to allow a certain request 16 | // depending on the underlying limiter decision. 17 | func (l *simpleLimiter) Limit(_ context.Context) error { 18 | if !l.limiter.Allow() { 19 | return fmt.Errorf("reached Rate-Limiting %v", l.limiter.Limit()) 20 | } 21 | 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /chapter1/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 1 - Networking Primer 2 | 3 | The files contained in this folder are [Wireshark](https://www.wireshark.org/) capture files. Each of them show the logs for different types of gRPC API. Their purpose is to illustrate the HTTP/2 protocol used by gRPC. You can view the captures in Wireshark by changing the HTTP/2 protocol TCP port to 50051 (Mac: `Preferences > Protocols > HTTP2 > TCP port(s)`, Linux/Windows: `Settings > Protocols > HTTP2 > TCP port(s)`), opening them (`File > Open`), and adding the following display filter: 4 | 5 | ``` 6 | tcp.port == 50051 and (grpc or http2) 7 | ``` 8 | -------------------------------------------------------------------------------- /chapter2/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 2 - Protobuf Primer 2 | 3 | These text files in this folder represent the values that we want to serialize. With these we can create an instance of `Account` (defined in `account.proto`) or Wrappers (defined in `wrappers.proto`), and encode data to binary. 4 | 5 | An example of encoding is the following: 6 | 7 | ## Linux/Mac 8 | ```shell 9 | cat account.txt | protoc --encode=Account account.proto | hexdump -C 10 | ``` 11 | 12 | ## Windows (Powershell) 13 | 14 | ```shell 15 | (Get-Content account.txt | protoc --encode=Account account.proto) -join "`n" | Format-Hex 16 | ``` -------------------------------------------------------------------------------- /chapter4/server/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "server", 5 | embed = [":server_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "server_lib", 12 | srcs = ["main.go"], 13 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 14 | visibility = ["//visibility:private"], 15 | deps = [ 16 | "@org_golang_google_grpc//:go_default_library", 17 | ], 18 | ) 19 | -------------------------------------------------------------------------------- /chapter5/client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/client 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | google.golang.org/grpc v1.63.2 10 | google.golang.org/protobuf v1.33.0 11 | ) 12 | 13 | require ( 14 | golang.org/x/net v0.24.0 // indirect 15 | golang.org/x/sys v0.19.0 // indirect 16 | golang.org/x/text v0.14.0 // indirect 17 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /chapter5/server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/server 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | google.golang.org/grpc v1.63.2 10 | google.golang.org/protobuf v1.33.0 11 | ) 12 | 13 | require ( 14 | golang.org/x/net v0.24.0 // indirect 15 | golang.org/x/sys v0.19.0 // indirect 16 | golang.org/x/text v0.14.0 // indirect 17 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /chapter6/client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/client 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | google.golang.org/grpc v1.63.2 10 | google.golang.org/protobuf v1.33.0 11 | ) 12 | 13 | require ( 14 | golang.org/x/net v0.24.0 // indirect 15 | golang.org/x/sys v0.19.0 // indirect 16 | golang.org/x/text v0.14.0 // indirect 17 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /chapter7/client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/client 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | google.golang.org/grpc v1.63.2 10 | google.golang.org/protobuf v1.33.0 11 | ) 12 | 13 | require ( 14 | golang.org/x/net v0.24.0 // indirect 15 | golang.org/x/sys v0.19.0 // indirect 16 | golang.org/x/text v0.14.0 // indirect 17 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /chapter4/client/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "client", 5 | embed = [":client_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "client_lib", 12 | srcs = ["main.go"], 13 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 14 | visibility = ["//visibility:private"], 15 | deps = [ 16 | "@org_golang_google_grpc//:go_default_library", 17 | "@org_golang_google_grpc//credentials/insecure", 18 | ], 19 | ) 20 | -------------------------------------------------------------------------------- /chapter9/server/test_options.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type testOptions struct { 4 | isAvailable bool 5 | } 6 | 7 | var defaultTestOptions = testOptions{ 8 | isAvailable: true, 9 | } 10 | 11 | type TestOption interface { 12 | apply(*testOptions) 13 | } 14 | 15 | type funcTestOption struct { 16 | f func(*testOptions) 17 | } 18 | 19 | func (fdo *funcTestOption) apply(do *testOptions) { 20 | fdo.f(do) 21 | } 22 | 23 | func newFuncTestOption(f func(*testOptions)) *funcTestOption { 24 | return &funcTestOption{ 25 | f: f, 26 | } 27 | } 28 | 29 | func IsAvailable(a bool) TestOption { 30 | return newFuncTestOption(func(o *testOptions) { 31 | o.isAvailable = a 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /chapter6/server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/server 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 10 | google.golang.org/grpc v1.63.2 11 | google.golang.org/protobuf v1.33.0 12 | ) 13 | 14 | require ( 15 | golang.org/x/net v0.24.0 // indirect 16 | golang.org/x/sys v0.19.0 // indirect 17 | golang.org/x/text v0.14.0 // indirect 18 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /chapter7/server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/server 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 10 | google.golang.org/grpc v1.63.2 11 | google.golang.org/protobuf v1.33.0 12 | ) 13 | 14 | require ( 15 | golang.org/x/net v0.24.0 // indirect 16 | golang.org/x/sys v0.19.0 // indirect 17 | golang.org/x/text v0.14.0 // indirect 18 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /chapter4/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "google.golang.org/grpc" 8 | "google.golang.org/grpc/credentials/insecure" 9 | ) 10 | 11 | func main() { 12 | args := os.Args[1:] 13 | 14 | if len(args) == 0 { 15 | log.Fatalln("usage: client [IP_ADDR]") 16 | } 17 | 18 | addr := args[0] 19 | opts := []grpc.DialOption{ 20 | grpc.WithTransportCredentials(insecure.NewCredentials()), 21 | } 22 | conn, err := grpc.Dial(addr, opts...) 23 | 24 | if err != nil { 25 | log.Fatalf("did not connect: %v", err) 26 | } 27 | 28 | defer func(conn *grpc.ClientConn) { 29 | if err := conn.Close(); err != nil { 30 | log.Fatalf("unexpected error: %v", err) 31 | } 32 | }(conn) 33 | } 34 | -------------------------------------------------------------------------------- /scripts/dockerbuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script is for maintenance of the projects. 4 | # It is supposed to be run inside a chapter folder. 5 | 6 | # If the buildx node is not created, uncomment the line below 7 | # sudo docker buildx create --name mybuild --driver=docker-container 8 | sudo docker buildx build \ 9 | --tag clementjean/packt-book:server \ 10 | --file server/Dockerfile \ 11 | --platform linux/arm64,linux/amd64 \ 12 | --builder mybuild \ 13 | --push . 14 | 15 | sudo docker buildx build \ 16 | --tag clementjean/packt-book:client \ 17 | --file client/Dockerfile \ 18 | --build-arg SERVER_ADDR="dns:///todo-server.default.svc.cluster.local:50051" \ 19 | --platform linux/arm64,linux/amd64 \ 20 | --builder mybuild \ 21 | --push . -------------------------------------------------------------------------------- /chapter5/client/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "client", 5 | embed = [":client_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "client_lib", 12 | srcs = ["main.go"], 13 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 14 | visibility = ["//visibility:private"], 15 | deps = [ 16 | "//proto/todo/v1:todo", 17 | "@org_golang_google_grpc//:go_default_library", 18 | "@org_golang_google_grpc//credentials/insecure", 19 | "@org_golang_google_protobuf//types/known/timestamppb", 20 | ], 21 | ) 22 | -------------------------------------------------------------------------------- /chapter3/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_library( 4 | name = "lib", 5 | srcs = ["main.go"], 6 | importpath = "", 7 | visibility = ["//visibility:private"], 8 | deps = [ 9 | "//chapter3/proto", 10 | "@org_golang_google_protobuf//proto", 11 | ], 12 | ) 13 | 14 | go_binary( 15 | name = "chapter3", 16 | embed = [":chapter3_lib"], 17 | visibility = ["//visibility:public"], 18 | ) 19 | 20 | go_library( 21 | name = "chapter3_lib", 22 | srcs = ["main.go"], 23 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3", 24 | visibility = ["//visibility:private"], 25 | deps = [ 26 | "//chapter3/proto", 27 | "@org_golang_google_protobuf//proto", 28 | ], 29 | ) 30 | -------------------------------------------------------------------------------- /chapter8/client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/client 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 10 | google.golang.org/grpc v1.63.2 11 | google.golang.org/protobuf v1.33.0 12 | ) 13 | 14 | require ( 15 | github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect 16 | github.com/stretchr/testify v1.9.0 // indirect 17 | golang.org/x/net v0.24.0 // indirect 18 | golang.org/x/sys v0.19.0 // indirect 19 | golang.org/x/text v0.14.0 // indirect 20 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /chapter9/client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/client 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 10 | google.golang.org/grpc v1.63.2 11 | google.golang.org/protobuf v1.33.0 12 | ) 13 | 14 | require ( 15 | github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect 16 | github.com/stretchr/testify v1.9.0 // indirect 17 | golang.org/x/net v0.24.0 // indirect 18 | golang.org/x/sys v0.19.0 // indirect 19 | golang.org/x/text v0.14.0 // indirect 20 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /chapter2/wrappers.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | message Int32Value { 4 | int32 value = 1; 5 | } 6 | 7 | message SInt32Value { 8 | sint32 value = 1; 9 | } 10 | 11 | message Int64Value { 12 | int64 value = 1; 13 | } 14 | 15 | message SInt64Value { 16 | sint64 value = 1; 17 | } 18 | 19 | message Fixed32Value { 20 | fixed32 value = 1; 21 | } 22 | 23 | message Fixed64Value { 24 | fixed64 value = 1; 25 | } 26 | 27 | message FloatValue { 28 | float value = 1; 29 | } 30 | 31 | message DoubleValue { 32 | double value = 1; 33 | } 34 | 35 | message SFixed32Value { 36 | sfixed32 value = 1; 37 | } 38 | 39 | message SFixed64Value { 40 | sfixed64 value = 1; 41 | } 42 | 43 | message StringValue { 44 | string value = 1; 45 | } 46 | 47 | message RepeatedUInt64Values { 48 | repeated uint64 values = 1; 49 | } 50 | -------------------------------------------------------------------------------- /chapter5/server/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "server", 5 | embed = [":server_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "server_lib", 12 | srcs = [ 13 | "db.go", 14 | "impl.go", 15 | "in_memory.go", 16 | "main.go", 17 | "server.go", 18 | ], 19 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 20 | visibility = ["//visibility:private"], 21 | deps = [ 22 | "//proto/todo/v1:todo", 23 | "@org_golang_google_grpc//:go_default_library", 24 | "@org_golang_google_protobuf//types/known/timestamppb", 25 | ], 26 | ) 27 | -------------------------------------------------------------------------------- /chapter6/client/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "client", 5 | embed = [":client_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "client_lib", 12 | srcs = ["main.go"], 13 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 14 | visibility = ["//visibility:private"], 15 | deps = [ 16 | "//proto/todo/v2:todo", 17 | "@org_golang_google_grpc//:go_default_library", 18 | "@org_golang_google_grpc//credentials/insecure", 19 | "@org_golang_google_protobuf//types/known/fieldmaskpb", 20 | "@org_golang_google_protobuf//types/known/timestamppb", 21 | ], 22 | ) 23 | -------------------------------------------------------------------------------- /chapter4/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | "os" 7 | 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func main() { 12 | args := os.Args[1:] 13 | 14 | if len(args) == 0 { 15 | log.Fatalln("usage: server [IP_ADDR]") 16 | } 17 | 18 | addr := args[0] 19 | lis, err := net.Listen("tcp", addr) 20 | 21 | if err != nil { 22 | log.Fatalf("failed to listen: %v\n", err) 23 | } 24 | 25 | defer func(lis net.Listener) { 26 | if err := lis.Close(); err != nil { 27 | log.Fatalf("unexpected error: %v", err) 28 | } 29 | }(lis) 30 | 31 | var opts []grpc.ServerOption 32 | s := grpc.NewServer(opts...) 33 | 34 | //registration of endpoints 35 | 36 | log.Printf("listening at %s\n", addr) 37 | 38 | defer s.Stop() 39 | if err := s.Serve(lis); err != nil { 40 | log.Fatalf("failed to serve: %v\n", err) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /chapter4/proto/dummy/v1/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | 5 | proto_library( 6 | name = "proto_proto", 7 | srcs = ["dummy.proto"], 8 | visibility = ["//visibility:public"], 9 | ) 10 | 11 | go_proto_library( 12 | name = "v1_go_proto", 13 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 14 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/dummy/v1", 15 | proto = ":proto_proto", 16 | visibility = ["//visibility:public"], 17 | ) 18 | 19 | go_library( 20 | name = "dummy", 21 | embed = [":v1_go_proto"], 22 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/dummy/v1", 23 | visibility = ["//visibility:public"], 24 | ) 25 | -------------------------------------------------------------------------------- /chapter4/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 4 - Setting up a Project 2 | 3 | This folder is a template for gRPC project that is used throughout the remaining chapters. It uses a go workspace and multiple modules (proto, server, client). This folder also shows how to set different ways of building a gRPC project. 4 | 5 | ## protoc 6 | 7 | ```shell 8 | $ protoc --go_out=. --go_opt=module=github.com/PacktPublishing/gRPC-Go-for-Professionals \ 9 | --go-grpc_out=. --go-grpc_opt=module=github.com/PacktPublishing/gRPC-Go-for-Professionals \ 10 | proto/dummy/v1/dummy.proto 11 | $ go run ./server 0.0.0.0:50051 12 | listening at 0.0.0.0:50051 13 | ``` 14 | 15 | ## Buf 16 | 17 | ```shell 18 | $ buf generate proto 19 | $ go run ./server 0.0.0.0:50051 20 | listening at 0.0.0.0:50051 21 | ``` 22 | 23 | ## Bazel 24 | 25 | ```shell 26 | $ bazel run //:server 27 | listening at 0.0.0.0:50051 28 | ``` 29 | -------------------------------------------------------------------------------- /chapter8/k8s/server.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: todo-server 5 | spec: 6 | # Make this a headless service so that each endpoint will be exposed 7 | # as a separate DNS A record. 8 | clusterIP: None 9 | ports: 10 | - name: grpc 11 | port: 50051 12 | selector: 13 | app: todo-server 14 | 15 | --- 16 | 17 | apiVersion: apps/v1 18 | kind: Deployment 19 | metadata: 20 | name: todo-server 21 | labels: 22 | app: todo-server 23 | spec: 24 | replicas: 3 25 | selector: 26 | matchLabels: 27 | app: todo-server 28 | template: 29 | metadata: 30 | labels: 31 | app: todo-server 32 | spec: 33 | containers: 34 | - name: todo-server 35 | image: clementjean/packt-book:server 36 | # imagePullPolicy: Always 37 | ports: 38 | - name: grpc 39 | containerPort: 50051 -------------------------------------------------------------------------------- /helpers/split.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "google.golang.org/protobuf/proto" 8 | "google.golang.org/protobuf/reflect/protoreflect" 9 | 10 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/helpers/proto" 11 | ) 12 | 13 | // serializedSize calculates the serialized size of the msg. 14 | // It returns the number of bytes in which the msg was serialized. 15 | func serializedSize[M protoreflect.ProtoMessage](msg M) int { 16 | out, err := proto.Marshal(msg) 17 | 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | 22 | return len(out) 23 | } 24 | 25 | func main() { 26 | s := &pb.Split{Name: "Packt"} 27 | sz := serializedSize(s) 28 | 29 | fmt.Printf("With Name: %d\n", sz) 30 | 31 | s.Name = "" 32 | s.ComplexName = &pb.ComplexName{Name: "Packt"} 33 | sz = serializedSize(s) 34 | 35 | fmt.Printf("With ComplexName: %d\n", sz) 36 | } 37 | -------------------------------------------------------------------------------- /chapter7/k8s/server.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: todo-server 5 | spec: 6 | # Make this a headless service so that each endpoint will be exposed 7 | # as a separate DNS A record. 8 | clusterIP: None 9 | ports: 10 | - name: grpc 11 | port: 50051 12 | selector: 13 | app: todo-server 14 | 15 | --- 16 | 17 | apiVersion: apps/v1 18 | kind: Deployment 19 | metadata: 20 | name: todo-server 21 | labels: 22 | app: todo-server 23 | spec: 24 | replicas: 3 25 | selector: 26 | matchLabels: 27 | app: todo-server 28 | template: 29 | metadata: 30 | labels: 31 | app: todo-server 32 | spec: 33 | containers: 34 | - name: todo-server 35 | image: clementjean/grpc-go-packt-book:server 36 | # imagePullPolicy: Always 37 | ports: 38 | - name: grpc 39 | containerPort: 50051 -------------------------------------------------------------------------------- /chapter9/k8s/server.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: todo-server 5 | spec: 6 | # Make this a headless service so that each endpoint will be exposed 7 | # as a separate DNS A record. 8 | clusterIP: None 9 | ports: 10 | - name: grpc 11 | port: 50051 12 | selector: 13 | app: todo-server 14 | 15 | --- 16 | 17 | apiVersion: apps/v1 18 | kind: Deployment 19 | metadata: 20 | name: todo-server 21 | labels: 22 | app: todo-server 23 | spec: 24 | replicas: 3 25 | selector: 26 | matchLabels: 27 | app: todo-server 28 | template: 29 | metadata: 30 | labels: 31 | app: todo-server 32 | spec: 33 | containers: 34 | - name: todo-server 35 | image: clementjean/grpc-go-packt-book:server 36 | imagePullPolicy: Always 37 | ports: 38 | - name: grpc 39 | containerPort: 50051 -------------------------------------------------------------------------------- /proto/todo/v1/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | 5 | proto_library( 6 | name = "v1_proto", 7 | srcs = ["todo.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = ["@com_google_protobuf//:timestamp_proto"], 10 | ) 11 | 12 | go_proto_library( 13 | name = "v1_go_proto", 14 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 15 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 16 | proto = ":v1_proto", 17 | visibility = ["//visibility:public"], 18 | ) 19 | 20 | go_library( 21 | name = "todo", 22 | embed = [":v1_go_proto"], 23 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 24 | visibility = ["//visibility:public"], 25 | ) 26 | -------------------------------------------------------------------------------- /chapter5/proto/todo/v1/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | 5 | proto_library( 6 | name = "v1_proto", 7 | srcs = ["todo.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = ["@com_google_protobuf//:timestamp_proto"], 10 | ) 11 | 12 | go_proto_library( 13 | name = "v1_go_proto", 14 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 15 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 16 | proto = ":v1_proto", 17 | visibility = ["//visibility:public"], 18 | ) 19 | 20 | go_library( 21 | name = "todo", 22 | embed = [":v1_go_proto"], 23 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 24 | visibility = ["//visibility:public"], 25 | ) 26 | -------------------------------------------------------------------------------- /chapter6/proto/todo/v1/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | 5 | proto_library( 6 | name = "v1_proto", 7 | srcs = ["todo.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = ["@com_google_protobuf//:timestamp_proto"], 10 | ) 11 | 12 | go_proto_library( 13 | name = "v1_go_proto", 14 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 15 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 16 | proto = ":v1_proto", 17 | visibility = ["//visibility:public"], 18 | ) 19 | 20 | go_library( 21 | name = "todo", 22 | embed = [":v1_go_proto"], 23 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 24 | visibility = ["//visibility:public"], 25 | ) 26 | -------------------------------------------------------------------------------- /chapter7/proto/todo/v1/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | 5 | proto_library( 6 | name = "v1_proto", 7 | srcs = ["todo.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = ["@com_google_protobuf//:timestamp_proto"], 10 | ) 11 | 12 | go_proto_library( 13 | name = "v1_go_proto", 14 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 15 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 16 | proto = ":v1_proto", 17 | visibility = ["//visibility:public"], 18 | ) 19 | 20 | go_library( 21 | name = "todo", 22 | embed = [":v1_go_proto"], 23 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 24 | visibility = ["//visibility:public"], 25 | ) 26 | -------------------------------------------------------------------------------- /chapter9/proto/todo/v1/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 3 | load("@rules_proto//proto:defs.bzl", "proto_library") 4 | 5 | proto_library( 6 | name = "v1_proto", 7 | srcs = ["todo.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = ["@com_google_protobuf//:timestamp_proto"], 10 | ) 11 | 12 | go_proto_library( 13 | name = "v1_go_proto", 14 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 15 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 16 | proto = ":v1_proto", 17 | visibility = ["//visibility:public"], 18 | ) 19 | 20 | go_library( 21 | name = "todo", 22 | embed = [":v1_go_proto"], 23 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 24 | visibility = ["//visibility:public"], 25 | ) 26 | -------------------------------------------------------------------------------- /chapter3/go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 2 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 3 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 4 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 5 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 6 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 7 | google.golang.org/protobuf v1.29.1 h1:7QBf+IK2gx70Ap/hDsOmam3GE0v9HicjfEdAxE62UoM= 8 | google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 9 | google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= 10 | google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 11 | -------------------------------------------------------------------------------- /chapter6/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 6 - APIs’ Design Considerations 2 | 3 | > This is based on the work done in chapter5 folder. 4 | 5 | This folder shows how to improve the API presented in the chapter5 folder. The main code for the implementations can be found in the following files: 6 | 7 | - [client/main.go](client/main.go) 8 | - [server/impl.go](server/impl.go) 9 | 10 | ## Running the code 11 | 12 | ### Server 13 | 14 | #### **go run** 15 | 16 | ```shell 17 | $ buf generate proto # or with protoc (see chapter4/README.md) 18 | $ go run ./server 0.0.0.0:50051 19 | ``` 20 | 21 | #### **bazel run** 22 | 23 | ```shell 24 | $ bazel run //server:server 0.0.0.0:50051 25 | ``` 26 | 27 | ### Client 28 | 29 | #### **go run** 30 | 31 | ```shell 32 | # if not done before `buf generate proto` or with protoc (see chapter4/README.md) 33 | $ go run ./client 0.0.0.0:50051 34 | ``` 35 | 36 | #### **bazel run** 37 | 38 | ```shell 39 | $ bazel run //client:client 0.0.0.0:50051 40 | ``` -------------------------------------------------------------------------------- /proto/validate/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | 5 | proto_library( 6 | name = "validate_proto", 7 | srcs = ["validate.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = [ 10 | "@com_google_protobuf//:descriptor_proto", 11 | "@com_google_protobuf//:duration_proto", 12 | "@com_google_protobuf//:timestamp_proto", 13 | ], 14 | ) 15 | 16 | go_proto_library( 17 | name = "validate_go_proto", 18 | importpath = "github.com/envoyproxy/protoc-gen-validate/validate", 19 | proto = ":validate_proto", 20 | visibility = ["//visibility:public"], 21 | ) 22 | 23 | go_library( 24 | name = "validate", 25 | embed = [":validate_go_proto"], 26 | importpath = "github.com/envoyproxy/protoc-gen-validate/validate", 27 | visibility = ["//visibility:public"], 28 | ) 29 | -------------------------------------------------------------------------------- /chapter3/proto/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | 5 | proto_library( 6 | name = "proto_proto", 7 | srcs = [ 8 | "account.proto", 9 | "accounts.proto", 10 | ], 11 | visibility = ["//visibility:public"], 12 | deps = ["//:root_proto"], 13 | ) 14 | 15 | go_proto_library( 16 | name = "proto_go_proto", 17 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 18 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3/proto", 19 | proto = ":proto_proto", 20 | visibility = ["//visibility:public"], 21 | deps = ["//:account.proto"], 22 | ) 23 | 24 | go_library( 25 | name = "proto", 26 | embed = [":proto_go_proto"], 27 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3/proto", 28 | visibility = ["//visibility:public"], 29 | ) 30 | -------------------------------------------------------------------------------- /chapter8/proto/validate/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 3 | load("@rules_proto//proto:defs.bzl", "proto_library") 4 | 5 | proto_library( 6 | name = "validate_proto", 7 | srcs = ["validate.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = [ 10 | "@com_google_protobuf//:descriptor_proto", 11 | "@com_google_protobuf//:duration_proto", 12 | "@com_google_protobuf//:timestamp_proto", 13 | ], 14 | ) 15 | 16 | go_library( 17 | name = "validate", 18 | embed = [":validate_go_proto"], 19 | importpath = "github.com/envoyproxy/protoc-gen-validate/validate", 20 | visibility = ["//visibility:public"], 21 | ) 22 | 23 | go_proto_library( 24 | name = "validate_go_proto", 25 | importpath = "github.com/envoyproxy/protoc-gen-validate/validate", 26 | proto = ":validate_proto", 27 | visibility = ["//visibility:public"], 28 | ) 29 | -------------------------------------------------------------------------------- /chapter9/proto/validate/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 3 | load("@rules_proto//proto:defs.bzl", "proto_library") 4 | 5 | proto_library( 6 | name = "validate_proto", 7 | srcs = ["validate.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = [ 10 | "@com_google_protobuf//:descriptor_proto", 11 | "@com_google_protobuf//:duration_proto", 12 | "@com_google_protobuf//:timestamp_proto", 13 | ], 14 | ) 15 | 16 | go_proto_library( 17 | name = "validate_go_proto", 18 | importpath = "github.com/envoyproxy/protoc-gen-validate/validate", 19 | proto = ":validate_proto", 20 | visibility = ["//visibility:public"], 21 | ) 22 | 23 | go_library( 24 | name = "validate", 25 | embed = [":validate_go_proto"], 26 | importpath = "github.com/envoyproxy/protoc-gen-validate/validate", 27 | visibility = ["//visibility:public"], 28 | ) 29 | -------------------------------------------------------------------------------- /chapter6/proto/todo/v2/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | 5 | proto_library( 6 | name = "v2_proto", 7 | srcs = ["todo.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = [ 10 | "@com_google_protobuf//:field_mask_proto", 11 | "@com_google_protobuf//:timestamp_proto", 12 | ], 13 | ) 14 | 15 | go_proto_library( 16 | name = "v2_go_proto", 17 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 18 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 19 | proto = ":v2_proto", 20 | visibility = ["//visibility:public"], 21 | ) 22 | 23 | go_library( 24 | name = "todo", 25 | embed = [":v2_go_proto"], 26 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 27 | visibility = ["//visibility:public"], 28 | ) 29 | -------------------------------------------------------------------------------- /chapter7/proto/todo/v2/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_proto//proto:defs.bzl", "proto_library") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 3 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 4 | 5 | proto_library( 6 | name = "v2_proto", 7 | srcs = ["todo.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = [ 10 | "@com_google_protobuf//:field_mask_proto", 11 | "@com_google_protobuf//:timestamp_proto", 12 | ], 13 | ) 14 | 15 | go_proto_library( 16 | name = "v2_go_proto", 17 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 18 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 19 | proto = ":v2_proto", 20 | visibility = ["//visibility:public"], 21 | ) 22 | 23 | go_library( 24 | name = "todo", 25 | embed = [":v2_go_proto"], 26 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 27 | visibility = ["//visibility:public"], 28 | ) 29 | -------------------------------------------------------------------------------- /chapter5/server/main.go: -------------------------------------------------------------------------------- 1 | //go:build !test 2 | 3 | package main 4 | 5 | import ( 6 | "log" 7 | "net" 8 | "os" 9 | 10 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1" 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | func main() { 15 | args := os.Args[1:] 16 | 17 | if len(args) == 0 { 18 | log.Fatalln("usage: server [IP_ADDR]") 19 | } 20 | 21 | addr := args[0] 22 | lis, err := net.Listen("tcp", addr) 23 | 24 | if err != nil { 25 | log.Fatalf("failed to listen: %v\n", err) 26 | } 27 | 28 | defer func(lis net.Listener) { 29 | if err := lis.Close(); err != nil { 30 | log.Fatalf("unexpected error: %v", err) 31 | } 32 | }(lis) 33 | 34 | var opts []grpc.ServerOption 35 | s := grpc.NewServer(opts...) 36 | 37 | pb.RegisterTodoServiceServer(s, &server{ 38 | d: New(), 39 | }) 40 | 41 | log.Printf("listening at %s\n", addr) 42 | 43 | defer s.Stop() 44 | if err := s.Serve(lis); err != nil { 45 | log.Fatalf("failed to serve: %v\n", err) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /chapter6/server/main.go: -------------------------------------------------------------------------------- 1 | //go:build !test 2 | 3 | package main 4 | 5 | import ( 6 | "log" 7 | "net" 8 | "os" 9 | 10 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | func main() { 15 | args := os.Args[1:] 16 | 17 | if len(args) == 0 { 18 | log.Fatalln("usage: server [IP_ADDR]") 19 | } 20 | 21 | addr := args[0] 22 | lis, err := net.Listen("tcp", addr) 23 | 24 | if err != nil { 25 | log.Fatalf("failed to listen: %v\n", err) 26 | } 27 | 28 | defer func(lis net.Listener) { 29 | if err := lis.Close(); err != nil { 30 | log.Fatalf("unexpected error: %v", err) 31 | } 32 | }(lis) 33 | 34 | var opts []grpc.ServerOption 35 | s := grpc.NewServer(opts...) 36 | 37 | pb.RegisterTodoServiceServer(s, &server{ 38 | d: New(), 39 | }) 40 | 41 | log.Printf("listening at %s\n", addr) 42 | 43 | defer s.Stop() 44 | if err := s.Serve(lis); err != nil { 45 | log.Fatalf("failed to serve: %v\n", err) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /helpers/tags.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "google.golang.org/protobuf/proto" 8 | "google.golang.org/protobuf/reflect/protoreflect" 9 | 10 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/helpers/proto" 11 | ) 12 | 13 | // serializedSize calculates the serialized size of the msg. 14 | // It returns the number of bytes in which the msg was serialized. 15 | func serializedSize[M protoreflect.ProtoMessage](msg M) int { 16 | out, err := proto.Marshal(msg) 17 | 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | 22 | return len(out) 23 | } 24 | 25 | func main() { 26 | t := &pb.Tags{} 27 | tags := []int{1, 16, 2048, 262_144, 33_554_432, 536_870_911} 28 | fields := []*int32{&t.Tag, &t.Tag2, &t.Tag3, &t.Tag4, &t.Tag5, &t.Tag6} 29 | 30 | sz := serializedSize(t) 31 | fmt.Printf("0 - %d\n", sz) 32 | 33 | for i, f := range fields { 34 | *f = 1 35 | 36 | sz := serializedSize(t) 37 | fmt.Printf("%d - %d\n", tags[i], sz-(i+1)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /scripts/updateall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script is for maintenance of the projects. 4 | # It updates all the dependencies for the different 5 | # go projects. 6 | 7 | . ./scripts/constants.sh 8 | 9 | pwd=$(pwd) 10 | 11 | for nb in $CHAPTERS_NB 12 | do 13 | if [ -d "$pwd/chapter$nb" ] 14 | then 15 | echo "enter $pwd/chapter$nb" 16 | cd $pwd/chapter$nb 17 | protoc -Iproto --go_out=proto --go_opt=paths=source_relative --go-grpc_out=proto --go-grpc_opt=paths=source_relative --validate_out="lang=go,paths=source_relative:proto" $(find . -type f -name "*.proto") 18 | 19 | for dir in server proto client 20 | do 21 | echo "enter $dir" 22 | cd $pwd/chapter$nb/$dir 23 | go get -u -d ./... 24 | go mod tidy 25 | done 26 | 27 | go work sync 28 | bazel run //:gazelle-update-repos 29 | fi 30 | done 31 | 32 | echo "enter $pwd/helpers" 33 | cd $pwd/helpers 34 | go get -u -d ./... 35 | go mod tidy 36 | 37 | echo "enter $pwd/proto" 38 | cd $pwd/proto 39 | go get -u -d ./... 40 | go mod tidy 41 | -------------------------------------------------------------------------------- /chapter9/server/server_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net" 7 | 8 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 9 | 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/test/bufconn" 12 | ) 13 | 14 | const bufSize = 1024 * 1024 15 | 16 | var lis *bufconn.Listener 17 | var fakeDb *FakeDb = NewFakeDb() 18 | 19 | // init is called whenever the tests are called. 20 | // It creates the lis (bufconn.Listener) and 21 | // initialize the server by registering TodoService. 22 | func init() { 23 | lis = bufconn.Listen(bufSize) 24 | s := grpc.NewServer() 25 | 26 | var testServer *server = &server{ 27 | d: fakeDb, 28 | } 29 | 30 | pb.RegisterTodoServiceServer(s, testServer) 31 | 32 | go func() { 33 | if err := s.Serve(lis); err != nil && err.Error() != "closed" { 34 | log.Fatalf("Server exited with error: %v\n", err) 35 | } 36 | }() 37 | } 38 | 39 | func bufDialer(context.Context, string) (net.Conn, error) { 40 | return lis.Dial() 41 | } 42 | -------------------------------------------------------------------------------- /chapter5/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 5 - Type of gRPC Endpoints 2 | 3 | > This is based on the work done in chapter4 folder. 4 | 5 | This folder shows how to implement the different types of gRPC APIs (unary, server streaming, client streaming, and bidirectional streaming). The main code for the implementations can be found in the following files: 6 | 7 | - [client/main.go](client/main.go) 8 | - [server/impl.go](server/impl.go) 9 | 10 | ## Running the code 11 | 12 | ### Server 13 | 14 | #### **go run** 15 | 16 | ```shell 17 | $ buf generate proto # or with protoc (see chapter4/README.md) 18 | $ go run ./server 0.0.0.0:50051 19 | ``` 20 | 21 | #### **bazel run** 22 | 23 | ```shell 24 | $ bazel run //server:server 0.0.0.0:50051 25 | ``` 26 | 27 | ### Client 28 | 29 | #### **go run** 30 | 31 | ```shell 32 | # if not done before `buf generate proto` or with protoc (see chapter4/README.md) 33 | $ go run ./client 0.0.0.0:50051 34 | ``` 35 | 36 | #### **bazel run** 37 | 38 | ```shell 39 | $ bazel run //client:client 0.0.0.0:50051 40 | ``` -------------------------------------------------------------------------------- /chapter6/server/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "server", 5 | embed = [":server_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "server_lib", 12 | srcs = [ 13 | "db.go", 14 | "impl.go", 15 | "in_memory.go", 16 | "main.go", 17 | "server.go", 18 | ], 19 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 20 | visibility = ["//visibility:private"], 21 | deps = [ 22 | "//proto/todo/v2:todo", 23 | "@org_golang_google_grpc//:go_default_library", 24 | "@org_golang_google_protobuf//proto", 25 | "@org_golang_google_protobuf//reflect/protoreflect", 26 | "@org_golang_google_protobuf//types/known/fieldmaskpb", 27 | "@org_golang_google_protobuf//types/known/timestamppb", 28 | "@org_golang_x_exp//slices", 29 | ], 30 | ) 31 | -------------------------------------------------------------------------------- /chapter8/proto/todo/v1/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 3 | load("@rules_proto//proto:defs.bzl", "proto_library") 4 | 5 | proto_library( 6 | name = "v1_proto", 7 | srcs = ["todo.proto"], 8 | visibility = ["//visibility:public"], 9 | deps = ["@com_google_protobuf//:timestamp_proto"], 10 | ) 11 | 12 | go_library( 13 | name = "todo", 14 | embed = [":v1_go_proto"], 15 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 16 | visibility = ["//visibility:public"], 17 | ) 18 | 19 | go_library( 20 | name = "v1", 21 | srcs = ["todo.pb.validate.go"], 22 | importpath = "", 23 | visibility = ["//visibility:public"], 24 | ) 25 | 26 | go_proto_library( 27 | name = "v1_go_proto", 28 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 29 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1", 30 | proto = ":v1_proto", 31 | visibility = ["//visibility:public"], 32 | ) 33 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This Makefile is for maintenance of the projects. 2 | 3 | ifeq ($(OS), Windows_NT) 4 | HELP_CMD = Select-String "^[a-zA-Z_-]+:.*?\#\# .*$$" "./Makefile" | Foreach-Object { $$_data = $$_.matches -split ":.*?\#\# "; $$obj = New-Object PSCustomObject; Add-Member -InputObject $$obj -NotePropertyName ('Command') -NotePropertyValue $$_data[0]; Add-Member -InputObject $$obj -NotePropertyName ('Description') -NotePropertyValue $$_data[1]; $$obj } | Format-Table -HideTableHeaders @{Expression={ $$e = [char]27; "$$e[36m$$($$_.Command)$${e}[0m" }}, Description 5 | else 6 | HELP_CMD = grep -E '^[a-zA-Z_-]+:.*?\#\# .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?\#\# "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 7 | endif 8 | 9 | .DEFAULT_GOAL := help 10 | 11 | validate: ## Validates that all the project runs with go run and bazel run 12 | ./scripts/startupvalidator.sh 13 | 14 | update: ## Updates all the projects 15 | ./scripts/updateall.sh 16 | 17 | clean: ## Cleans all the generated files 18 | ./scripts/cleanall.sh 19 | 20 | help: ## Shows this help 21 | @${HELP_CMD} 22 | -------------------------------------------------------------------------------- /chapter7/client/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "client", 5 | embed = [":client_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "client_lib", 12 | srcs = [ 13 | "interceptors.go", 14 | "main.go", 15 | ], 16 | data = [ 17 | "//certs:ca_cert.pem", 18 | ], 19 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 20 | visibility = ["//visibility:private"], 21 | deps = [ 22 | "//proto/todo/v2:todo", 23 | "@org_golang_google_grpc//:go_default_library", 24 | "@org_golang_google_grpc//codes", 25 | "@org_golang_google_grpc//credentials", 26 | "@org_golang_google_grpc//metadata", 27 | "@org_golang_google_grpc//status", 28 | "@org_golang_google_protobuf//types/known/fieldmaskpb", 29 | "@org_golang_google_protobuf//types/known/timestamppb", 30 | ], 31 | ) 32 | -------------------------------------------------------------------------------- /BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | 3 | # gazelle:exclude proto/**/*.go 4 | # gazelle:exclude helpers 5 | # gazelle:prefix github.com/PacktPublishing/gRPC-Go-for-Professionals 6 | # gazelle:resolve go google.golang.org/protobuf/types/known/fieldmaskpb @org_golang_google_protobuf//types/known/fieldmaskpb 7 | # gazelle:resolve go google.golang.org/protobuf/types/known/timestamppb @org_golang_google_protobuf//types/known/timestamppb 8 | # gazelle:resolve go google.golang.org/protobuf/types/known/anypb @org_golang_google_protobuf//types/known/anypb 9 | # gazelle:resolve go github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1 //proto/todo/v1:todo 10 | # gazelle:resolve go github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2 //proto/todo/v2:todo 11 | gazelle(name = "gazelle") 12 | 13 | gazelle( 14 | name = "gazelle-update-repos", 15 | args = [ 16 | "-from_file=go.work", 17 | "-to_macro=deps.bzl%go_dependencies", 18 | "-prune", 19 | "-build_file_proto_mode=disable_global", 20 | ], 21 | command = "update-repos", 22 | ) 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /chapter8/client/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "client", 5 | embed = [":client_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "client_lib", 12 | srcs = [ 13 | "interceptors.go", 14 | "main.go", 15 | ], 16 | data = [ 17 | "//certs:ca_cert.pem", 18 | ], 19 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 20 | visibility = ["//visibility:private"], 21 | deps = [ 22 | "//proto/todo/v2:todo", 23 | "@com_github_grpc_ecosystem_go_grpc_middleware_v2//interceptors/retry", 24 | "@org_golang_google_grpc//:go_default_library", 25 | "@org_golang_google_grpc//codes", 26 | "@org_golang_google_grpc//credentials", 27 | "@org_golang_google_grpc//metadata", 28 | "@org_golang_google_grpc//status", 29 | "@org_golang_google_protobuf//types/known/fieldmaskpb", 30 | "@org_golang_google_protobuf//types/known/timestamppb", 31 | ], 32 | ) 33 | -------------------------------------------------------------------------------- /chapter4/proto/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 3 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 4 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 5 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 6 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 7 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 8 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 10 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 11 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 12 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 13 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 14 | -------------------------------------------------------------------------------- /chapter5/proto/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 3 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 4 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 5 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 6 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 7 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 8 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 10 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 11 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 12 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 13 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 14 | -------------------------------------------------------------------------------- /chapter6/proto/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 3 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 4 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 5 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 6 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 7 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 8 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 10 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 11 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 12 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 13 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 14 | -------------------------------------------------------------------------------- /chapter7/proto/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 3 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 4 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 5 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 6 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 7 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 8 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 10 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 11 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 12 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 13 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 14 | -------------------------------------------------------------------------------- /chapter7/client/interceptors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc" 7 | "google.golang.org/grpc/metadata" 8 | ) 9 | 10 | const authTokenKey string = "auth_token" 11 | const authTokenValue string = "authd" 12 | 13 | // unaryAuthInterceptor is an interceptor automatically adding the auth token 14 | // to a request. 15 | func unaryAuthInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { 16 | ctx = metadata.AppendToOutgoingContext(ctx, authTokenKey, authTokenValue) 17 | err := invoker(ctx, method, req, reply, cc, opts...) 18 | 19 | return err 20 | } 21 | 22 | // streamAuthInterceptor is an interceptor automatically adding the auth token 23 | // to a request. 24 | func streamAuthInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { 25 | ctx = metadata.AppendToOutgoingContext(ctx, authTokenKey, authTokenValue) 26 | s, err := streamer(ctx, desc, cc, method, opts...) 27 | 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | return s, nil 33 | } 34 | -------------------------------------------------------------------------------- /chapter8/client/interceptors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc" 7 | "google.golang.org/grpc/metadata" 8 | ) 9 | 10 | const authTokenKey string = "auth_token" 11 | const authTokenValue string = "authd" 12 | 13 | // unaryAuthInterceptor is an interceptor automatically adding the auth token 14 | // to a request. 15 | func unaryAuthInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { 16 | ctx = metadata.AppendToOutgoingContext(ctx, authTokenKey, authTokenValue) 17 | err := invoker(ctx, method, req, reply, cc, opts...) 18 | 19 | return err 20 | } 21 | 22 | // streamAuthInterceptor is an interceptor automatically adding the auth token 23 | // to a request. 24 | func streamAuthInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { 25 | ctx = metadata.AppendToOutgoingContext(ctx, authTokenKey, authTokenValue) 26 | s, err := streamer(ctx, desc, cc, method, opts...) 27 | 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | return s, nil 33 | } 34 | -------------------------------------------------------------------------------- /chapter9/client/interceptors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc" 7 | "google.golang.org/grpc/metadata" 8 | ) 9 | 10 | const authTokenKey string = "auth_token" 11 | const authTokenValue string = "authd" 12 | 13 | // unaryAuthInterceptor is an interceptor automatically adding the auth token 14 | // to a request. 15 | func unaryAuthInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { 16 | ctx = metadata.AppendToOutgoingContext(ctx, authTokenKey, authTokenValue) 17 | err := invoker(ctx, method, req, reply, cc, opts...) 18 | 19 | return err 20 | } 21 | 22 | // streamAuthInterceptor is an interceptor automatically adding the auth token 23 | // to a request. 24 | func streamAuthInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { 25 | ctx = metadata.AppendToOutgoingContext(ctx, authTokenKey, authTokenValue) 26 | s, err := streamer(ctx, desc, cc, method, opts...) 27 | 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | return s, nil 33 | } 34 | -------------------------------------------------------------------------------- /helpers/integers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "unsafe" 7 | 8 | "golang.org/x/exp/constraints" 9 | "google.golang.org/protobuf/proto" 10 | "google.golang.org/protobuf/reflect/protoreflect" 11 | "google.golang.org/protobuf/types/known/wrapperspb" 12 | ) 13 | 14 | // serializedSize calculates the size in memory of data 15 | // and the size after Protobuf serialization of the wrapper. 16 | // It returns two values. The number of bytes for data in memory 17 | // and the number of bytes after serialization of wrapper - 1 (removes the byte for tag + wire type). 18 | func serializedSize[D constraints.Integer, W protoreflect.ProtoMessage](data D, wrapper W) (uintptr, int) { 19 | out, err := proto.Marshal(wrapper) 20 | 21 | if err != nil { 22 | log.Fatal(err) 23 | } 24 | 25 | return unsafe.Sizeof(data), len(out) - 1 26 | } 27 | 28 | func main() { 29 | var data int32 = 268_435_456 30 | i32 := &wrapperspb.Int32Value{ 31 | Value: data, 32 | } 33 | 34 | // var data uint64 = 72_057_594_037_927_936 35 | // ui64 := &wrapperspb.UInt64Value{ 36 | // Value: data, 37 | // } 38 | 39 | d, w := serializedSize(data, i32) 40 | fmt.Printf("in memory: %d\npb: %d\n", d, w) 41 | } 42 | -------------------------------------------------------------------------------- /go.work.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 2 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 4 | golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= 5 | golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 6 | golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= 7 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 8 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 9 | golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 10 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 11 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 12 | golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= 13 | golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= 14 | google.golang.org/genproto v0.0.0-20230525234025-438c736192d0 h1:x1vNwUhVOcsYoKyEGCZBH694SBmmBjA2EfauFVEI2+M= 15 | -------------------------------------------------------------------------------- /chapter9/client/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "client", 5 | embed = [":client_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "client_lib", 12 | srcs = [ 13 | "interceptors.go", 14 | "main.go", 15 | ], 16 | data = [ 17 | "//certs:ca_cert.pem", 18 | ], 19 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/client", 20 | visibility = ["//visibility:private"], 21 | deps = [ 22 | "//proto/todo/v2:todo", 23 | "@com_github_grpc_ecosystem_go_grpc_middleware_v2//interceptors/retry", 24 | "@org_golang_google_grpc//:go_default_library", 25 | "@org_golang_google_grpc//codes", 26 | "@org_golang_google_grpc//credentials", 27 | "@org_golang_google_grpc//credentials/insecure", 28 | "@org_golang_google_grpc//metadata", 29 | "@org_golang_google_grpc//status", 30 | "@org_golang_google_protobuf//types/known/fieldmaskpb", 31 | "@org_golang_google_protobuf//types/known/timestamppb", 32 | ], 33 | ) 34 | -------------------------------------------------------------------------------- /helpers/README.md: -------------------------------------------------------------------------------- 1 | # Helpers 2 | 3 | ## Proto 4 | 5 | In order to build the proto files in the `proto` folder, you can run the following command: 6 | 7 | ```shell 8 | protoc --go_out=. --go_opt=paths=source_relative proto/*.proto 9 | ``` 10 | 11 | This should generate files and give you the following: 12 | 13 | ```shell 14 | proto 15 | ├── split.pb.go 16 | ├── split.proto 17 | ├── tags.pb.go 18 | ├── tags.proto 19 | ├── todo.pb.go 20 | └── todo.proto 21 | ``` 22 | 23 | ## Go 24 | 25 | > Before you read this section, make sure that you generated the go code from the proto files (see previous section). 26 | 27 | There are multiple `main` functions in this folder so you cannot do a simple `go run`. You will have to specify the helper you want to run: 28 | 29 | ### Integers 30 | 31 | ```shell 32 | $ go run integers.go 33 | in memory: 4 34 | pb: 5 35 | ``` 36 | 37 | ### Tags 38 | 39 | ```shell 40 | $ go run tags.go 41 | 0 - 0 42 | 1 - 1 43 | 16 - 3 44 | 2048 - 6 45 | 262144 - 10 46 | 33554432 - 15 47 | 536870911 - 20 48 | ``` 49 | 50 | ### Split 51 | 52 | ```shell 53 | $ go run split.go 54 | With Name: 7 55 | With ComplexName: 9 56 | ``` 57 | 58 | ### Gzip 59 | 60 | ```shell 61 | $ go run gzip.go 62 | original: 191 63 | compressed: 180 64 | ``` -------------------------------------------------------------------------------- /proto/todo/v2/BUILD.bazel: -------------------------------------------------------------------------------- 1 | # gazelle:resolve proto validate/validate.proto @com_envoyproxy_protoc_gen_validate//validate:validate_proto 2 | 3 | load("@rules_proto//proto:defs.bzl", "proto_library") 4 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 5 | load("@com_envoyproxy_protoc_gen_validate//bazel:pgv_proto_library.bzl", "pgv_go_proto_library") 6 | 7 | proto_library( 8 | name = "v2_proto", 9 | srcs = ["todo.proto"], 10 | visibility = ["//visibility:public"], 11 | deps = [ 12 | "@com_envoyproxy_protoc_gen_validate//validate:validate_proto", 13 | "@com_google_protobuf//:field_mask_proto", 14 | "@com_google_protobuf//:timestamp_proto", 15 | ], 16 | ) 17 | 18 | pgv_go_proto_library( 19 | name = "v2_go_proto", 20 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 21 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 22 | proto = ":v2_proto", 23 | deps = ["@com_envoyproxy_protoc_gen_validate//validate:validate_go"], 24 | ) 25 | 26 | go_library( 27 | name = "todo", 28 | embed = [":v2_go_proto"], 29 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 30 | visibility = ["//visibility:public"], 31 | ) 32 | -------------------------------------------------------------------------------- /proto/todo/v1/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v1; 4 | 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1"; 8 | 9 | message Task { 10 | uint64 id = 1; 11 | string description = 2; 12 | bool done = 3; 13 | google.protobuf.Timestamp due_date = 4; 14 | } 15 | 16 | message AddTaskRequest { 17 | string description = 1; 18 | google.protobuf.Timestamp due_date = 2; 19 | } 20 | 21 | message AddTaskResponse { 22 | uint64 id = 1; 23 | } 24 | 25 | message ListTasksRequest { 26 | } 27 | 28 | message ListTasksResponse { 29 | Task task = 1; 30 | bool overdue = 2; 31 | } 32 | 33 | message UpdateTasksRequest { 34 | Task task = 1; 35 | } 36 | 37 | message UpdateTasksResponse { 38 | } 39 | 40 | message DeleteTasksRequest { 41 | uint64 id = 1; 42 | } 43 | 44 | message DeleteTasksResponse { 45 | } 46 | 47 | service TodoService { 48 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 49 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 50 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 51 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 52 | } -------------------------------------------------------------------------------- /chapter9/proto/todo/v2/BUILD.bazel: -------------------------------------------------------------------------------- 1 | # gazelle:resolve proto validate/validate.proto @com_envoyproxy_protoc_gen_validate//validate:validate_proto 2 | 3 | load("@com_envoyproxy_protoc_gen_validate//bazel:pgv_proto_library.bzl", "pgv_go_proto_library") 4 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 5 | load("@rules_proto//proto:defs.bzl", "proto_library") 6 | 7 | proto_library( 8 | name = "v2_proto", 9 | srcs = ["todo.proto"], 10 | visibility = ["//visibility:public"], 11 | deps = [ 12 | "@com_envoyproxy_protoc_gen_validate//validate:validate_proto", 13 | "@com_google_protobuf//:field_mask_proto", 14 | "@com_google_protobuf//:timestamp_proto", 15 | ], 16 | ) 17 | 18 | pgv_go_proto_library( 19 | name = "v2_go_proto", 20 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 21 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 22 | proto = ":v2_proto", 23 | deps = ["@com_envoyproxy_protoc_gen_validate//validate:validate_go"], 24 | ) 25 | 26 | go_library( 27 | name = "todo", 28 | embed = [":v2_go_proto"], 29 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 30 | visibility = ["//visibility:public"], 31 | ) 32 | -------------------------------------------------------------------------------- /chapter5/proto/todo/v1/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v1; 4 | 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1"; 8 | 9 | message Task { 10 | uint64 id = 1; 11 | string description = 2; 12 | bool done = 3; 13 | google.protobuf.Timestamp due_date = 4; 14 | } 15 | 16 | message AddTaskRequest { 17 | string description = 1; 18 | google.protobuf.Timestamp due_date = 2; 19 | } 20 | 21 | message AddTaskResponse { 22 | uint64 id = 1; 23 | } 24 | 25 | message ListTasksRequest { 26 | } 27 | 28 | message ListTasksResponse { 29 | Task task = 1; 30 | bool overdue = 2; 31 | } 32 | 33 | message UpdateTasksRequest { 34 | Task task = 1; 35 | } 36 | 37 | message UpdateTasksResponse { 38 | } 39 | 40 | message DeleteTasksRequest { 41 | uint64 id = 1; 42 | } 43 | 44 | message DeleteTasksResponse { 45 | } 46 | 47 | service TodoService { 48 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 49 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 50 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 51 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 52 | } -------------------------------------------------------------------------------- /chapter6/proto/todo/v1/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v1; 4 | 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1"; 8 | 9 | message Task { 10 | uint64 id = 1; 11 | string description = 2; 12 | bool done = 3; 13 | google.protobuf.Timestamp due_date = 4; 14 | } 15 | 16 | message AddTaskRequest { 17 | string description = 1; 18 | google.protobuf.Timestamp due_date = 2; 19 | } 20 | 21 | message AddTaskResponse { 22 | uint64 id = 1; 23 | } 24 | 25 | message ListTasksRequest { 26 | } 27 | 28 | message ListTasksResponse { 29 | Task task = 1; 30 | bool overdue = 2; 31 | } 32 | 33 | message UpdateTasksRequest { 34 | Task task = 1; 35 | } 36 | 37 | message UpdateTasksResponse { 38 | } 39 | 40 | message DeleteTasksRequest { 41 | uint64 id = 1; 42 | } 43 | 44 | message DeleteTasksResponse { 45 | } 46 | 47 | service TodoService { 48 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 49 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 50 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 51 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 52 | } -------------------------------------------------------------------------------- /chapter7/proto/todo/v1/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v1; 4 | 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1"; 8 | 9 | message Task { 10 | uint64 id = 1; 11 | string description = 2; 12 | bool done = 3; 13 | google.protobuf.Timestamp due_date = 4; 14 | } 15 | 16 | message AddTaskRequest { 17 | string description = 1; 18 | google.protobuf.Timestamp due_date = 2; 19 | } 20 | 21 | message AddTaskResponse { 22 | uint64 id = 1; 23 | } 24 | 25 | message ListTasksRequest { 26 | } 27 | 28 | message ListTasksResponse { 29 | Task task = 1; 30 | bool overdue = 2; 31 | } 32 | 33 | message UpdateTasksRequest { 34 | Task task = 1; 35 | } 36 | 37 | message UpdateTasksResponse { 38 | } 39 | 40 | message DeleteTasksRequest { 41 | uint64 id = 1; 42 | } 43 | 44 | message DeleteTasksResponse { 45 | } 46 | 47 | service TodoService { 48 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 49 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 50 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 51 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 52 | } -------------------------------------------------------------------------------- /chapter8/proto/todo/v1/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v1; 4 | 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1"; 8 | 9 | message Task { 10 | uint64 id = 1; 11 | string description = 2; 12 | bool done = 3; 13 | google.protobuf.Timestamp due_date = 4; 14 | } 15 | 16 | message AddTaskRequest { 17 | string description = 1; 18 | google.protobuf.Timestamp due_date = 2; 19 | } 20 | 21 | message AddTaskResponse { 22 | uint64 id = 1; 23 | } 24 | 25 | message ListTasksRequest { 26 | } 27 | 28 | message ListTasksResponse { 29 | Task task = 1; 30 | bool overdue = 2; 31 | } 32 | 33 | message UpdateTasksRequest { 34 | Task task = 1; 35 | } 36 | 37 | message UpdateTasksResponse { 38 | } 39 | 40 | message DeleteTasksRequest { 41 | uint64 id = 1; 42 | } 43 | 44 | message DeleteTasksResponse { 45 | } 46 | 47 | service TodoService { 48 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 49 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 50 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 51 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 52 | } -------------------------------------------------------------------------------- /chapter9/proto/todo/v1/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v1; 4 | 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1"; 8 | 9 | message Task { 10 | uint64 id = 1; 11 | string description = 2; 12 | bool done = 3; 13 | google.protobuf.Timestamp due_date = 4; 14 | } 15 | 16 | message AddTaskRequest { 17 | string description = 1; 18 | google.protobuf.Timestamp due_date = 2; 19 | } 20 | 21 | message AddTaskResponse { 22 | uint64 id = 1; 23 | } 24 | 25 | message ListTasksRequest { 26 | } 27 | 28 | message ListTasksResponse { 29 | Task task = 1; 30 | bool overdue = 2; 31 | } 32 | 33 | message UpdateTasksRequest { 34 | Task task = 1; 35 | } 36 | 37 | message UpdateTasksResponse { 38 | } 39 | 40 | message DeleteTasksRequest { 41 | uint64 id = 1; 42 | } 43 | 44 | message DeleteTasksResponse { 45 | } 46 | 47 | service TodoService { 48 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 49 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 50 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 51 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 52 | } -------------------------------------------------------------------------------- /chapter4/client/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 4 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 5 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 6 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 7 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 8 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 10 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 11 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 12 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 13 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 14 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 15 | -------------------------------------------------------------------------------- /chapter4/server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 4 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 5 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 6 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 7 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 8 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 10 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 11 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 12 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 13 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 14 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 15 | -------------------------------------------------------------------------------- /chapter5/client/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 4 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 5 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 6 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 7 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 8 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 10 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 11 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 12 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 13 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 14 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 15 | -------------------------------------------------------------------------------- /chapter5/server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 4 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 5 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 6 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 7 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 8 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 10 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 11 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 12 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 13 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 14 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 15 | -------------------------------------------------------------------------------- /chapter6/client/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 4 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 5 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 6 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 7 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 8 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 10 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 11 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 12 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 13 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 14 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 15 | -------------------------------------------------------------------------------- /chapter7/client/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 4 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 5 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 6 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 7 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 8 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 9 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 10 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 11 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 12 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 13 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 14 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 15 | -------------------------------------------------------------------------------- /versions.bzl: -------------------------------------------------------------------------------- 1 | """Defines the dependencies' versions. 2 | 3 | This allow us to keep the book generic and update cheaply the versions. 4 | """ 5 | 6 | # Go 7 | # The last version can be found here: https://go.dev/dl/ 8 | # Note: You do not need to download the last version locally, 9 | # Just update this variable. Bazel will download it for you. 10 | GO_VERSION = "1.22.2" 11 | 12 | # Rules_go 13 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/rules_go/releases 14 | RULES_GO_VERSION = "v0.46.0" 15 | RULES_GO_SHA256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184" 16 | 17 | # Gazelle 18 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/bazel-gazelle/blob/master/README.rst 19 | GAZELLE_VERSION = "v0.36.0" 20 | GAZELLE_SHA256 = "b7387f72efb59f876e4daae42f1d3912d0d45563eac7cb23d1de0b094ab588cf" 21 | 22 | # Protobuf 23 | # The last version can be found here: https://github.com/protocolbuffers/protobuf/releases 24 | # Note: You do not need to download the last version locally, 25 | # Just update this variable. Bazel will download it for you. 26 | PROTO_VERSION = "v25.0" 27 | 28 | # protoc-gen-validate 29 | # The last version can be found here: https://github.com/bufbuild/protoc-gen-validate/releases 30 | PROTOC_GEN_VALIDATE_VERSION = "v1.0.1" 31 | -------------------------------------------------------------------------------- /chapter4/versions.bzl: -------------------------------------------------------------------------------- 1 | """Defines the dependencies' versions. 2 | 3 | This allow us to keep the book generic and update cheaply the versions. 4 | """ 5 | 6 | # Go 7 | # The last version can be found here: https://go.dev/dl/ 8 | # Note: You do not need to download the last version locally, 9 | # Just update this variable. Bazel will download it for you. 10 | GO_VERSION = "1.22.2" 11 | 12 | # Rules_go 13 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/rules_go/releases 14 | RULES_GO_VERSION = "v0.46.0" 15 | RULES_GO_SHA256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184" 16 | 17 | # Gazelle 18 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/bazel-gazelle/blob/master/README.rst 19 | GAZELLE_VERSION = "v0.36.0" 20 | GAZELLE_SHA256 = "b7387f72efb59f876e4daae42f1d3912d0d45563eac7cb23d1de0b094ab588cf" 21 | 22 | # Protobuf 23 | # The last version can be found here: https://github.com/protocolbuffers/protobuf/releases 24 | # Note: You do not need to download the last version locally, 25 | # Just update this variable. Bazel will download it for you. 26 | PROTO_VERSION = "v25.0" 27 | 28 | # protoc-gen-validate 29 | # The last version can be found here: https://github.com/bufbuild/protoc-gen-validate/releases 30 | PROTOC_GEN_VALIDATE_VERSION = "v1.0.1" 31 | -------------------------------------------------------------------------------- /chapter5/versions.bzl: -------------------------------------------------------------------------------- 1 | """Defines the dependencies' versions. 2 | 3 | This allow us to keep the book generic and update cheaply the versions. 4 | """ 5 | 6 | # Go 7 | # The last version can be found here: https://go.dev/dl/ 8 | # Note: You do not need to download the last version locally, 9 | # Just update this variable. Bazel will download it for you. 10 | GO_VERSION = "1.22.2" 11 | 12 | # Rules_go 13 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/rules_go/releases 14 | RULES_GO_VERSION = "v0.46.0" 15 | RULES_GO_SHA256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184" 16 | 17 | # Gazelle 18 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/bazel-gazelle/blob/master/README.rst 19 | GAZELLE_VERSION = "v0.36.0" 20 | GAZELLE_SHA256 = "b7387f72efb59f876e4daae42f1d3912d0d45563eac7cb23d1de0b094ab588cf" 21 | 22 | # Protobuf 23 | # The last version can be found here: https://github.com/protocolbuffers/protobuf/releases 24 | # Note: You do not need to download the last version locally, 25 | # Just update this variable. Bazel will download it for you. 26 | PROTO_VERSION = "v25.0" 27 | 28 | # protoc-gen-validate 29 | # The last version can be found here: https://github.com/bufbuild/protoc-gen-validate/releases 30 | PROTOC_GEN_VALIDATE_VERSION = "v1.0.1" 31 | -------------------------------------------------------------------------------- /chapter6/versions.bzl: -------------------------------------------------------------------------------- 1 | """Defines the dependencies' versions. 2 | 3 | This allow us to keep the book generic and update cheaply the versions. 4 | """ 5 | 6 | # Go 7 | # The last version can be found here: https://go.dev/dl/ 8 | # Note: You do not need to download the last version locally, 9 | # Just update this variable. Bazel will download it for you. 10 | GO_VERSION = "1.22.2" 11 | 12 | # Rules_go 13 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/rules_go/releases 14 | RULES_GO_VERSION = "v0.46.0" 15 | RULES_GO_SHA256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184" 16 | 17 | # Gazelle 18 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/bazel-gazelle/blob/master/README.rst 19 | GAZELLE_VERSION = "v0.36.0" 20 | GAZELLE_SHA256 = "b7387f72efb59f876e4daae42f1d3912d0d45563eac7cb23d1de0b094ab588cf" 21 | 22 | # Protobuf 23 | # The last version can be found here: https://github.com/protocolbuffers/protobuf/releases 24 | # Note: You do not need to download the last version locally, 25 | # Just update this variable. Bazel will download it for you. 26 | PROTO_VERSION = "v25.0" 27 | 28 | # protoc-gen-validate 29 | # The last version can be found here: https://github.com/bufbuild/protoc-gen-validate/releases 30 | PROTOC_GEN_VALIDATE_VERSION = "v1.0.1" 31 | -------------------------------------------------------------------------------- /chapter7/versions.bzl: -------------------------------------------------------------------------------- 1 | """Defines the dependencies' versions. 2 | 3 | This allow us to keep the book generic and update cheaply the versions. 4 | """ 5 | 6 | # Go 7 | # The last version can be found here: https://go.dev/dl/ 8 | # Note: You do not need to download the last version locally, 9 | # Just update this variable. Bazel will download it for you. 10 | GO_VERSION = "1.22.2" 11 | 12 | # Rules_go 13 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/rules_go/releases 14 | RULES_GO_VERSION = "v0.46.0" 15 | RULES_GO_SHA256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184" 16 | 17 | # Gazelle 18 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/bazel-gazelle/blob/master/README.rst 19 | GAZELLE_VERSION = "v0.36.0" 20 | GAZELLE_SHA256 = "b7387f72efb59f876e4daae42f1d3912d0d45563eac7cb23d1de0b094ab588cf" 21 | 22 | # Protobuf 23 | # The last version can be found here: https://github.com/protocolbuffers/protobuf/releases 24 | # Note: You do not need to download the last version locally, 25 | # Just update this variable. Bazel will download it for you. 26 | PROTO_VERSION = "v25.0" 27 | 28 | # protoc-gen-validate 29 | # The last version can be found here: https://github.com/bufbuild/protoc-gen-validate/releases 30 | PROTOC_GEN_VALIDATE_VERSION = "v1.0.1" 31 | -------------------------------------------------------------------------------- /chapter8/versions.bzl: -------------------------------------------------------------------------------- 1 | """Defines the dependencies' versions. 2 | 3 | This allow us to keep the book generic and update cheaply the versions. 4 | """ 5 | 6 | # Go 7 | # The last version can be found here: https://go.dev/dl/ 8 | # Note: You do not need to download the last version locally, 9 | # Just update this variable. Bazel will download it for you. 10 | GO_VERSION = "1.22.2" 11 | 12 | # Rules_go 13 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/rules_go/releases 14 | RULES_GO_VERSION = "v0.46.0" 15 | RULES_GO_SHA256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184" 16 | 17 | # Gazelle 18 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/bazel-gazelle/blob/master/README.rst 19 | GAZELLE_VERSION = "v0.36.0" 20 | GAZELLE_SHA256 = "b7387f72efb59f876e4daae42f1d3912d0d45563eac7cb23d1de0b094ab588cf" 21 | 22 | # Protobuf 23 | # The last version can be found here: https://github.com/protocolbuffers/protobuf/releases 24 | # Note: You do not need to download the last version locally, 25 | # Just update this variable. Bazel will download it for you. 26 | PROTO_VERSION = "v25.0" 27 | 28 | # protoc-gen-validate 29 | # The last version can be found here: https://github.com/bufbuild/protoc-gen-validate/releases 30 | PROTOC_GEN_VALIDATE_VERSION = "v1.0.1" 31 | -------------------------------------------------------------------------------- /chapter9/versions.bzl: -------------------------------------------------------------------------------- 1 | """Defines the dependencies' versions. 2 | 3 | This allow us to keep the book generic and update cheaply the versions. 4 | """ 5 | 6 | # Go 7 | # The last version can be found here: https://go.dev/dl/ 8 | # Note: You do not need to download the last version locally, 9 | # Just update this variable. Bazel will download it for you. 10 | GO_VERSION = "1.22.2" 11 | 12 | # Rules_go 13 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/rules_go/releases 14 | RULES_GO_VERSION = "v0.46.0" 15 | RULES_GO_SHA256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184" 16 | 17 | # Gazelle 18 | # The last version and SHA256 can be found here: https://github.com/bazelbuild/bazel-gazelle/blob/master/README.rst 19 | GAZELLE_VERSION = "v0.36.0" 20 | GAZELLE_SHA256 = "b7387f72efb59f876e4daae42f1d3912d0d45563eac7cb23d1de0b094ab588cf" 21 | 22 | # Protobuf 23 | # The last version can be found here: https://github.com/protocolbuffers/protobuf/releases 24 | # Note: You do not need to download the last version locally, 25 | # Just update this variable. Bazel will download it for you. 26 | PROTO_VERSION = "v25.0" 27 | 28 | # protoc-gen-validate 29 | # The last version can be found here: https://github.com/bufbuild/protoc-gen-validate/releases 30 | PROTOC_GEN_VALIDATE_VERSION = "v1.0.1" 31 | -------------------------------------------------------------------------------- /chapter7/server/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "server", 5 | embed = [":server_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "server_lib", 12 | srcs = [ 13 | "db.go", 14 | "impl.go", 15 | "in_memory.go", 16 | "interceptors.go", 17 | "main.go", 18 | "server.go", 19 | ], 20 | data = [ 21 | "//certs:server_cert.pem", 22 | "//certs:server_key.pem", 23 | ], 24 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 25 | visibility = ["//visibility:private"], 26 | deps = [ 27 | "//proto/todo/v2:todo", 28 | "@org_golang_google_grpc//:go_default_library", 29 | "@org_golang_google_grpc//codes", 30 | "@org_golang_google_grpc//credentials", 31 | "@org_golang_google_grpc//metadata", 32 | "@org_golang_google_grpc//status", 33 | "@org_golang_google_protobuf//proto", 34 | "@org_golang_google_protobuf//reflect/protoreflect", 35 | "@org_golang_google_protobuf//types/known/fieldmaskpb", 36 | "@org_golang_google_protobuf//types/known/timestamppb", 37 | "@org_golang_x_exp//slices", 38 | ], 39 | ) 40 | -------------------------------------------------------------------------------- /chapter8/proto/todo/v2/BUILD.bazel: -------------------------------------------------------------------------------- 1 | # gazelle:resolve proto validate/validate.proto @com_envoyproxy_protoc_gen_validate//validate:validate_proto 2 | 3 | load("@com_envoyproxy_protoc_gen_validate//bazel:pgv_proto_library.bzl", "pgv_go_proto_library") 4 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 5 | load("@rules_proto//proto:defs.bzl", "proto_library") 6 | 7 | proto_library( 8 | name = "v2_proto", 9 | srcs = ["todo.proto"], 10 | visibility = ["//visibility:public"], 11 | deps = [ 12 | "@com_envoyproxy_protoc_gen_validate//validate:validate_proto", 13 | "@com_google_protobuf//:field_mask_proto", 14 | "@com_google_protobuf//:timestamp_proto", 15 | ], 16 | ) 17 | 18 | pgv_go_proto_library( 19 | name = "v2_go_proto", 20 | compilers = ["@io_bazel_rules_go//proto:go_grpc"], 21 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 22 | proto = ":v2_proto", 23 | deps = ["@com_envoyproxy_protoc_gen_validate//validate:validate_go"], 24 | ) 25 | 26 | go_library( 27 | name = "todo", 28 | embed = [":v2_go_proto"], 29 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2", 30 | visibility = ["//visibility:public"], 31 | ) 32 | 33 | go_library( 34 | name = "v2", 35 | srcs = ["todo.pb.validate.go"], 36 | importpath = "", 37 | visibility = ["//visibility:public"], 38 | ) 39 | -------------------------------------------------------------------------------- /chapter6/proto/todo/v2/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v2; 4 | 5 | import "google/protobuf/field_mask.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | 8 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2"; 9 | 10 | message Task { 11 | uint64 id = 1; 12 | string description = 2; 13 | bool done = 3; 14 | google.protobuf.Timestamp due_date = 4; 15 | } 16 | 17 | message AddTaskRequest { 18 | string description = 1; 19 | google.protobuf.Timestamp due_date = 2; 20 | } 21 | 22 | message AddTaskResponse { 23 | uint64 id = 1; 24 | } 25 | 26 | message ListTasksRequest { 27 | google.protobuf.FieldMask mask = 1; 28 | } 29 | 30 | message ListTasksResponse { 31 | Task task = 1; 32 | bool overdue = 2; 33 | } 34 | 35 | message UpdateTasksRequest { 36 | uint64 id = 1; 37 | string description = 2; 38 | bool done = 3; 39 | google.protobuf.Timestamp due_date = 4; 40 | } 41 | 42 | message UpdateTasksResponse { 43 | } 44 | 45 | message DeleteTasksRequest { 46 | uint64 id = 1; 47 | } 48 | 49 | message DeleteTasksResponse { 50 | } 51 | 52 | service TodoService { 53 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 54 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 55 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 56 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 57 | } -------------------------------------------------------------------------------- /chapter7/proto/todo/v2/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v2; 4 | 5 | import "google/protobuf/field_mask.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | 8 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2"; 9 | 10 | message Task { 11 | uint64 id = 1; 12 | string description = 2; 13 | bool done = 3; 14 | google.protobuf.Timestamp due_date = 4; 15 | } 16 | 17 | message AddTaskRequest { 18 | string description = 1; 19 | google.protobuf.Timestamp due_date = 2; 20 | } 21 | 22 | message AddTaskResponse { 23 | uint64 id = 1; 24 | } 25 | 26 | message ListTasksRequest { 27 | google.protobuf.FieldMask mask = 1; 28 | } 29 | 30 | message ListTasksResponse { 31 | Task task = 1; 32 | bool overdue = 2; 33 | } 34 | 35 | message UpdateTasksRequest { 36 | uint64 id = 1; 37 | string description = 2; 38 | bool done = 3; 39 | google.protobuf.Timestamp due_date = 4; 40 | } 41 | 42 | message UpdateTasksResponse { 43 | } 44 | 45 | message DeleteTasksRequest { 46 | uint64 id = 1; 47 | } 48 | 49 | message DeleteTasksResponse { 50 | } 51 | 52 | service TodoService { 53 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 54 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 55 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 56 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 57 | } -------------------------------------------------------------------------------- /proto/go.sum: -------------------------------------------------------------------------------- 1 | github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= 2 | github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= 3 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 4 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 5 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 6 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 7 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 8 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 9 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 10 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 11 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 12 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 13 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 14 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 15 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 16 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 17 | -------------------------------------------------------------------------------- /chapter7/server/main.go: -------------------------------------------------------------------------------- 1 | //go:build !test 2 | 3 | package main 4 | 5 | import ( 6 | "log" 7 | "net" 8 | "os" 9 | 10 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 11 | "google.golang.org/grpc" 12 | "google.golang.org/grpc/credentials" 13 | //_ "google.golang.org/grpc/encoding/gzip" 14 | ) 15 | 16 | func main() { 17 | args := os.Args[1:] 18 | 19 | if len(args) == 0 { 20 | log.Fatalln("usage: server [IP_ADDR]") 21 | } 22 | 23 | addr := args[0] 24 | lis, err := net.Listen("tcp", addr) 25 | 26 | if err != nil { 27 | log.Fatalf("failed to listen: %v\n", err) 28 | } 29 | 30 | defer func(lis net.Listener) { 31 | if err := lis.Close(); err != nil { 32 | log.Fatalf("unexpected error: %v", err) 33 | } 34 | }(lis) 35 | 36 | creds, err := credentials.NewServerTLSFromFile("./certs/server_cert.pem", "./certs/server_key.pem") 37 | if err != nil { 38 | log.Fatalf("failed to create credentials: %v", err) 39 | } 40 | 41 | opts := []grpc.ServerOption{ 42 | grpc.Creds(creds), 43 | grpc.ChainUnaryInterceptor(unaryAuthInterceptor, unaryLogInterceptor), 44 | grpc.ChainStreamInterceptor(streamAuthInterceptor, streamLogInterceptor), 45 | } 46 | s := grpc.NewServer(opts...) 47 | 48 | pb.RegisterTodoServiceServer(s, &server{ 49 | d: New(), 50 | }) 51 | 52 | log.Printf("listening at %s\n", addr) 53 | 54 | defer s.Stop() 55 | if err := s.Serve(lis); err != nil { 56 | log.Fatalf("failed to serve: %v\n", err) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /chapter8/proto/go.sum: -------------------------------------------------------------------------------- 1 | github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= 2 | github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= 3 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 4 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 5 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 6 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 7 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 8 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 9 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 10 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 11 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 12 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 13 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 14 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 15 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 16 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 17 | -------------------------------------------------------------------------------- /chapter9/proto/go.sum: -------------------------------------------------------------------------------- 1 | github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= 2 | github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= 3 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 4 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 5 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 6 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 7 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 8 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 9 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 10 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 11 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 12 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 13 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 14 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 15 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 16 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 17 | -------------------------------------------------------------------------------- /chapter6/server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc= 4 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= 5 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 6 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 7 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 8 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 9 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 10 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 11 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 12 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 13 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 14 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 15 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 16 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 17 | -------------------------------------------------------------------------------- /chapter7/server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 2 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 3 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc= 4 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= 5 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 6 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 7 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 8 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 9 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 10 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 11 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 12 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 13 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 14 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 15 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 16 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 17 | -------------------------------------------------------------------------------- /chapter9/server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/server 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 10 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 11 | github.com/prometheus/client_golang v1.19.0 12 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.50.0 13 | golang.org/x/sync v0.7.0 14 | golang.org/x/time v0.5.0 15 | google.golang.org/grpc v1.63.2 16 | google.golang.org/protobuf v1.33.0 17 | ) 18 | 19 | require ( 20 | github.com/beorn7/perks v1.0.1 // indirect 21 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 22 | github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect 23 | github.com/go-logr/logr v1.4.1 // indirect 24 | github.com/go-logr/stdr v1.2.2 // indirect 25 | github.com/prometheus/client_model v0.6.1 // indirect 26 | github.com/prometheus/common v0.52.3 // indirect 27 | github.com/prometheus/procfs v0.13.0 // indirect 28 | go.opentelemetry.io/otel v1.25.0 // indirect 29 | go.opentelemetry.io/otel/metric v1.25.0 // indirect 30 | go.opentelemetry.io/otel/trace v1.25.0 // indirect 31 | golang.org/x/net v0.24.0 // indirect 32 | golang.org/x/sys v0.19.0 // indirect 33 | golang.org/x/text v0.14.0 // indirect 34 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 35 | ) 36 | -------------------------------------------------------------------------------- /helpers/gzip.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "compress/gzip" 6 | "fmt" 7 | "log" 8 | "time" 9 | 10 | "google.golang.org/protobuf/proto" 11 | "google.golang.org/protobuf/reflect/protoreflect" 12 | "google.golang.org/protobuf/types/known/timestamppb" 13 | 14 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/helpers/proto" 15 | ) 16 | 17 | // compressedSize calculates the number of bytes after compression with gzip. 18 | // It returns two values. The number of bytes the msg takes after serialization 19 | // and the number of bytes after compression. 20 | func compressedSize[M protoreflect.ProtoMessage](msg M) (int, int) { 21 | var b bytes.Buffer 22 | gz := gzip.NewWriter(&b) 23 | out, err := proto.Marshal(msg) 24 | 25 | if err != nil { 26 | log.Fatal(err) 27 | } 28 | 29 | if _, err := gz.Write(out); err != nil { 30 | log.Fatal(err) 31 | } 32 | 33 | if err := gz.Close(); err != nil { 34 | log.Fatal(err) 35 | } 36 | 37 | return len(out), len(b.Bytes()) 38 | } 39 | 40 | func main() { 41 | // var data int32 = 268_435_456 42 | // i32 := &wrapperspb.Int32Value{ 43 | // Value: data, 44 | // } 45 | 46 | task := &pb.Task{ 47 | Id: 1, 48 | Description: `This is a task that is quite long and requires a lot of work. 49 | We are not sure we can finish it even after 5 days. 50 | Some planning will be needed and a meeting is required.`, 51 | DueDate: timestamppb.New(time.Now().Add(5 * 24 * time.Hour)), 52 | } 53 | 54 | o, c := compressedSize(task) 55 | fmt.Printf("original: %d\ncompressed: %d\n", o, c) 56 | } 57 | -------------------------------------------------------------------------------- /chapter8/proto/todo/v2/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v2; 4 | 5 | import "google/protobuf/field_mask.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | import "validate/validate.proto"; 8 | 9 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2"; 10 | 11 | message Task { 12 | uint64 id = 1; 13 | string description = 2; 14 | bool done = 3; 15 | google.protobuf.Timestamp due_date = 4; 16 | } 17 | 18 | message AddTaskRequest { 19 | string description = 1 [ 20 | (validate.rules).string.min_len = 1 21 | ]; 22 | 23 | google.protobuf.Timestamp due_date = 2 [ 24 | (validate.rules).timestamp.gt_now = true 25 | ]; 26 | } 27 | 28 | message AddTaskResponse { 29 | uint64 id = 1; 30 | } 31 | 32 | message ListTasksRequest { 33 | google.protobuf.FieldMask mask = 1; 34 | } 35 | 36 | message ListTasksResponse { 37 | Task task = 1; 38 | bool overdue = 2; 39 | } 40 | 41 | message UpdateTasksRequest { 42 | uint64 id = 1; 43 | string description = 2; 44 | bool done = 3; 45 | google.protobuf.Timestamp due_date = 4; 46 | } 47 | 48 | message UpdateTasksResponse { 49 | } 50 | 51 | message DeleteTasksRequest { 52 | uint64 id = 1; 53 | } 54 | 55 | message DeleteTasksResponse { 56 | } 57 | 58 | service TodoService { 59 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 60 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 61 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 62 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 63 | } -------------------------------------------------------------------------------- /chapter8/server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PacktPublishing/gRPC-Go-for-Professionals/server 2 | 3 | go 1.22 4 | 5 | replace github.com/PacktPublishing/gRPC-Go-for-Professionals/proto => ../proto 6 | 7 | require ( 8 | github.com/PacktPublishing/gRPC-Go-for-Professionals/proto v0.0.0-20240314031024-bbcc94dd9932 9 | github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 10 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 11 | github.com/prometheus/client_golang v1.19.0 12 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.50.0 13 | golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 14 | golang.org/x/sync v0.7.0 15 | golang.org/x/time v0.5.0 16 | google.golang.org/grpc v1.63.2 17 | google.golang.org/protobuf v1.33.0 18 | ) 19 | 20 | require ( 21 | github.com/beorn7/perks v1.0.1 // indirect 22 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 23 | github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect 24 | github.com/go-logr/logr v1.4.1 // indirect 25 | github.com/go-logr/stdr v1.2.2 // indirect 26 | github.com/prometheus/client_model v0.6.1 // indirect 27 | github.com/prometheus/common v0.52.3 // indirect 28 | github.com/prometheus/procfs v0.13.0 // indirect 29 | go.opentelemetry.io/otel v1.25.0 // indirect 30 | go.opentelemetry.io/otel/metric v1.25.0 // indirect 31 | go.opentelemetry.io/otel/trace v1.25.0 // indirect 32 | golang.org/x/net v0.24.0 // indirect 33 | golang.org/x/sys v0.19.0 // indirect 34 | golang.org/x/text v0.14.0 // indirect 35 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect 36 | ) 37 | -------------------------------------------------------------------------------- /proto/todo/v2/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v2; 4 | 5 | import "google/protobuf/field_mask.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | import "validate/validate.proto"; 8 | 9 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2"; 10 | 11 | message Task { 12 | uint64 id = 1; 13 | string description = 2; 14 | bool done = 3; 15 | google.protobuf.Timestamp due_date = 4; 16 | } 17 | 18 | message AddTaskRequest { 19 | string description = 1 [ 20 | (validate.rules).string.min_len = 1 21 | ]; 22 | 23 | google.protobuf.Timestamp due_date = 2 [ 24 | (validate.rules).timestamp.gt_now = true, 25 | (validate.rules).timestamp.required = true 26 | ]; 27 | } 28 | 29 | message AddTaskResponse { 30 | uint64 id = 1; 31 | } 32 | 33 | message ListTasksRequest { 34 | google.protobuf.FieldMask mask = 1; 35 | } 36 | 37 | message ListTasksResponse { 38 | Task task = 1; 39 | bool overdue = 2; 40 | } 41 | 42 | message UpdateTasksRequest { 43 | uint64 id = 1; 44 | string description = 2; 45 | bool done = 3; 46 | google.protobuf.Timestamp due_date = 4; 47 | } 48 | 49 | message UpdateTasksResponse { 50 | } 51 | 52 | message DeleteTasksRequest { 53 | uint64 id = 1; 54 | } 55 | 56 | message DeleteTasksResponse { 57 | } 58 | 59 | service TodoService { 60 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 61 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 62 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 63 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 64 | } -------------------------------------------------------------------------------- /chapter9/proto/todo/v2/todo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package todo.v2; 4 | 5 | import "google/protobuf/field_mask.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | import "validate/validate.proto"; 8 | 9 | option go_package = "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2"; 10 | 11 | message Task { 12 | uint64 id = 1; 13 | string description = 2; 14 | bool done = 3; 15 | google.protobuf.Timestamp due_date = 4; 16 | } 17 | 18 | message AddTaskRequest { 19 | string description = 1 [ 20 | (validate.rules).string.min_len = 1 21 | ]; 22 | 23 | google.protobuf.Timestamp due_date = 2 [ 24 | (validate.rules).timestamp.gt_now = true, 25 | (validate.rules).timestamp.required = true 26 | ]; 27 | } 28 | 29 | message AddTaskResponse { 30 | uint64 id = 1; 31 | } 32 | 33 | message ListTasksRequest { 34 | google.protobuf.FieldMask mask = 1; 35 | } 36 | 37 | message ListTasksResponse { 38 | Task task = 1; 39 | bool overdue = 2; 40 | } 41 | 42 | message UpdateTasksRequest { 43 | uint64 id = 1; 44 | string description = 2; 45 | bool done = 3; 46 | google.protobuf.Timestamp due_date = 4; 47 | } 48 | 49 | message UpdateTasksResponse { 50 | } 51 | 52 | message DeleteTasksRequest { 53 | uint64 id = 1; 54 | } 55 | 56 | message DeleteTasksResponse { 57 | } 58 | 59 | service TodoService { 60 | rpc AddTask(AddTaskRequest) returns (AddTaskResponse); 61 | rpc ListTasks(ListTasksRequest) returns (stream ListTasksResponse); 62 | rpc UpdateTasks(stream UpdateTasksRequest) returns (UpdateTasksResponse); 63 | rpc DeleteTasks(stream DeleteTasksRequest) returns (stream DeleteTasksResponse); 64 | } -------------------------------------------------------------------------------- /chapter3/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 3 - Introduction to gRPC 2 | 3 | This folder contains the result of comparing Protobuf and JSON in order to explain one of the reasons gRPC is faster than traditional REST APIs. You can find the result of the size comparison by taking a look at the files named `accounts.bin.gz` and `accounts.json.gz`. And you can execute the serialization/deserialization time comparison by running the `main.go` file. 4 | 5 | ## Size 6 | 7 | ### Linux/Mac 8 | 9 | ```shell 10 | $ ls -lh *.gz 11 | 571K accounts.bin.gz 12 | 650K accounts.json.gz 13 | ``` 14 | 15 | ### Windows (Powershell) 16 | 17 | ```shell 18 | $ Get-ChildItem *.gz | Select-Object Name, @{Name="Size (KB)";Expression={$_.Length / 1KB}} 19 | Name Size (KB) 20 | ---- --------- 21 | accounts.bin.gz 570.806 22 | accounts.json.gz 650.103 23 | ``` 24 | 25 | ## Serialization/Deserialization Time 26 | 27 | > Be aware that if you have generated gRPC code (proto/account_grpc.pb.go) before you will have a dependency error. Simply remove proto/account_grpc.pb.go before running the following commands. 28 | 29 | ```shell 30 | $ gzip -dk *.gz 31 | $ protoc --proto_path=proto \ 32 | --go_out=. --go_opt=module=github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3 \ 33 | proto/*.proto 34 | $ go run main.go 35 | JSON: 40.520000ms 36 | PB: 9.450000ms 37 | ``` 38 | 39 | ## Generating both Protobuf and gRPC code 40 | 41 | ```shell 42 | $ protoc --proto_path=proto \ 43 | --go_out=. --go_opt=module=github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3 \ 44 | --go-grpc_out=. --go-grpc_opt=module=github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3 \ 45 | proto/*.proto 46 | ``` 47 | -------------------------------------------------------------------------------- /chapter9/server/fake_db.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | type FakeDb struct { 9 | d *inMemoryDb 10 | opts testOptions 11 | } 12 | 13 | func NewFakeDb(opt ...TestOption) *FakeDb { 14 | opts := defaultTestOptions 15 | for _, o := range opt { 16 | o.apply(&opts) 17 | } 18 | 19 | return &FakeDb{ 20 | d: &inMemoryDb{}, 21 | opts: opts, 22 | } 23 | } 24 | 25 | func (db *FakeDb) Reset() { 26 | db.opts = defaultTestOptions 27 | db.d = &inMemoryDb{} 28 | } 29 | 30 | func (db *FakeDb) addTask(description string, dueDate time.Time) (uint64, error) { 31 | if !db.opts.isAvailable { 32 | return 0, fmt.Errorf( 33 | "couldn't access the database", 34 | ) 35 | } 36 | return db.d.addTask(description, dueDate) 37 | } 38 | 39 | func (db *FakeDb) getTasks(f func(interface{}) error) error { 40 | if !db.opts.isAvailable { 41 | return fmt.Errorf( 42 | // the error message is different only because we 43 | // do not handle the error, we directly return it 44 | // in ListTasks. For other endpoints, we generally 45 | // prepend with "unexpected error: ". 46 | "unexpected error: couldn't access the database", 47 | ) 48 | } 49 | return db.d.getTasks(f) 50 | } 51 | 52 | func (db *FakeDb) updateTask(id uint64, description string, dueDate time.Time, done bool) error { 53 | if !db.opts.isAvailable { 54 | return fmt.Errorf( 55 | "couldn't access the database", 56 | ) 57 | } 58 | return db.d.updateTask(id, description, dueDate, done) 59 | } 60 | 61 | func (db *FakeDb) deleteTask(id uint64) error { 62 | if !db.opts.isAvailable { 63 | return fmt.Errorf( 64 | "couldn't access the database", 65 | ) 66 | } 67 | return db.d.deleteTask(id) 68 | } 69 | -------------------------------------------------------------------------------- /chapter7/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 7 - Out of the box features 2 | 3 | > This is based on the work done in chapter6 folder. 4 | 5 | This folder shows how more advanced features that comes out of the box with gRPC (error handling, interceptors, load balancing, ...). The main code for the implementations can be found in the following files: 6 | 7 | - [client/main.go](client/main.go) 8 | - [client/interceptors.go](client/interceptors.go) 9 | - [server/impl.go](server/impl.go) 10 | - [server/interceptors.go](server/interceptors.go) 11 | 12 | ## Running the code 13 | 14 | ### Server 15 | 16 | #### **go run** 17 | 18 | ```shell 19 | $ buf generate proto # or with protoc (see chapter4/README.md) 20 | $ go run ./server 0.0.0.0:50051 21 | ``` 22 | 23 | #### **bazel run** 24 | 25 | ```shell 26 | $ bazel run //server:server 0.0.0.0:50051 27 | ``` 28 | 29 | ### Client 30 | 31 | #### **go run** 32 | 33 | ```shell 34 | # if not done before `buf generate proto` or with protoc (see chapter4/README.md) 35 | $ go run ./client 0.0.0.0:50051 36 | ``` 37 | 38 | #### **bazel run** 39 | 40 | ```shell 41 | $ bazel run //client:client 0.0.0.0:50051 42 | ``` 43 | 44 | ### Kubernetes (k8s) 45 | 46 | In order to show the load balancing effects, this folder introduces configurations for deploying the server and client to Kubernetes. 47 | 48 | > A Kubernetes is required in order to make the following command work. If you have [kind](https://kind.sigs.k8s.io/) installed, you can run the following command to quickly spin up a cluster: `kind create cluster --config k8s/kind.yaml`. 49 | 50 | #### **Server** 51 | 52 | ```shell 53 | $ kubectl apply -f k8s/server.yaml 54 | ``` 55 | 56 | #### **Client** 57 | 58 | ```shell 59 | $ kubectl apply -f k8s/client.yaml 60 | ``` -------------------------------------------------------------------------------- /chapter8/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 8 - More essential features 2 | 3 | > This is based on the work done in chapter7 folder. 4 | 5 | This folder shows other essential features (validating, tracing, rate limiting, ...) that can be added with [protoc-gen-validate](https://github.com/bufbuild/protoc-gen-validate) and [go-grpc-middleware](https://github.com/grpc-ecosystem/go-grpc-middleware). The main code for the implementations can be found in the following files: 6 | 7 | - [client/main.go](client/main.go) 8 | - [client/interceptors.go](client/interceptors.go) 9 | - [server/impl.go](server/impl.go) 10 | - [server/interceptors.go](server/interceptors.go) 11 | - [server/limit.go](server/limit.go) 12 | 13 | ## Running the code 14 | 15 | ### Server 16 | 17 | #### **go run** 18 | 19 | ```shell 20 | $ buf generate proto # or with protoc (see chapter4/README.md) 21 | $ go run ./server 0.0.0.0:50051 0.0.0.0:50052 22 | ``` 23 | 24 | #### **bazel run** 25 | 26 | ```shell 27 | $ bazel run //server:server 0.0.0.0:50051 0.0.0.0:50052 28 | ``` 29 | 30 | ### Client 31 | 32 | #### **go run** 33 | 34 | ```shell 35 | # if not done before `buf generate proto` or with protoc (see chapter4/README.md) 36 | $ go run ./client 0.0.0.0:50051 37 | ``` 38 | 39 | #### **bazel run** 40 | 41 | ```shell 42 | $ bazel run //client:client 0.0.0.0:50051 43 | ``` 44 | 45 | ## Prometheus 46 | 47 | Once the client made some requests to the server, Prometheus exposes metrics on the /metrics route of the HTTP server. If you ran the following command: 48 | 49 | ```shell 50 | $ go run ./server 0.0.0.0:50051 0.0.0.0:50052 51 | ``` 52 | 53 | the second address is the HTTP server address. This means that you can access the metrics like so: 54 | 55 | ```shell 56 | $ curl http://localhost:50052/metrics 57 | ``` -------------------------------------------------------------------------------- /certs/server_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | yaBwLiXfcvZrZOwy 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /chapter8/server/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_binary( 4 | name = "server", 5 | embed = [":server_lib"], 6 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 7 | visibility = ["//visibility:public"], 8 | ) 9 | 10 | go_library( 11 | name = "server_lib", 12 | srcs = [ 13 | "db.go", 14 | "impl.go", 15 | "in_memory.go", 16 | "interceptors.go", 17 | "limit.go", 18 | "main.go", 19 | "server.go", 20 | ], 21 | data = [ 22 | "//certs:server_cert.pem", 23 | "//certs:server_key.pem", 24 | ], 25 | importpath = "github.com/PacktPublishing/gRPC-Go-for-Professionals/server", 26 | visibility = ["//visibility:private"], 27 | deps = [ 28 | "//proto/todo/v2:todo", 29 | "@com_github_grpc_ecosystem_go_grpc_middleware_providers_prometheus//:prometheus", 30 | "@com_github_grpc_ecosystem_go_grpc_middleware_v2//interceptors/auth", 31 | "@com_github_grpc_ecosystem_go_grpc_middleware_v2//interceptors/logging", 32 | "@com_github_grpc_ecosystem_go_grpc_middleware_v2//interceptors/ratelimit", 33 | "@com_github_prometheus_client_golang//prometheus", 34 | "@com_github_prometheus_client_golang//prometheus/promhttp", 35 | "@io_opentelemetry_go_contrib_instrumentation_google_golang_org_grpc_otelgrpc//:otelgrpc", 36 | "@org_golang_google_grpc//:go_default_library", 37 | "@org_golang_google_grpc//codes", 38 | "@org_golang_google_grpc//credentials", 39 | "@org_golang_google_grpc//metadata", 40 | "@org_golang_google_grpc//status", 41 | "@org_golang_google_protobuf//proto", 42 | "@org_golang_google_protobuf//reflect/protoreflect", 43 | "@org_golang_google_protobuf//types/known/fieldmaskpb", 44 | "@org_golang_google_protobuf//types/known/timestamppb", 45 | "@org_golang_x_exp//slices", 46 | "@org_golang_x_sync//errgroup", 47 | "@org_golang_x_time//rate", 48 | ], 49 | ) 50 | -------------------------------------------------------------------------------- /chapter7/certs/server_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | yaBwLiXfcvZrZOwy 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /chapter8/certs/server_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | yaBwLiXfcvZrZOwy 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /chapter9/certs/server_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | yaBwLiXfcvZrZOwy 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /chapter3/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | "os" 7 | "time" 8 | 9 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/chapter3/proto" 10 | "google.golang.org/protobuf/proto" 11 | ) 12 | 13 | type AccountJSON struct { 14 | Id int64 `json:"id"` 15 | UserName string `json:"username"` 16 | } 17 | 18 | type AccountsJSON struct { 19 | Values []AccountJSON 20 | } 21 | 22 | // readFromJSON reads JSON data from accounts.json. 23 | // It returns the time (time.Duration) it took deserialize the data. 24 | func readFromJSON() time.Duration { 25 | data, err := os.ReadFile("accounts.json") 26 | if err != nil { 27 | log.Fatalln(err) 28 | } 29 | 30 | var accounts AccountsJSON 31 | 32 | start := time.Now() 33 | if err := json.Unmarshal(data, &accounts.Values); err != nil { 34 | log.Fatalf("failed to unmarshal: %v\n", err) 35 | } 36 | return time.Since(start) 37 | } 38 | 39 | // readFromPB reads Protobuf data from accounts.bin. 40 | // It returns the time (time.Duration) it took deserialize the data. 41 | func readFromPB() time.Duration { 42 | in, err := os.ReadFile("accounts.bin") 43 | if err != nil { 44 | log.Fatalln(err) 45 | } 46 | 47 | var data pb.Accounts 48 | 49 | start := time.Now() 50 | if err = proto.Unmarshal(in, &data); err != nil { 51 | log.Fatalln("failed to unmarshal: %v\n", err) 52 | } 53 | return time.Since(start) 54 | } 55 | 56 | // the number of data samples. 57 | const sizeData int = 100 58 | 59 | // mean calculate the arithmetic mean of multiple time.Duration. 60 | // It returns the mean in milliseconds. 61 | func mean(data [sizeData]time.Duration) float64 { 62 | var sum float64 63 | 64 | for _, d := range data { 65 | sum += float64(d.Milliseconds()) 66 | } 67 | 68 | return sum / float64(len(data)) 69 | } 70 | 71 | func main() { 72 | var jsonTimes [sizeData]time.Duration 73 | var pbTimes [sizeData]time.Duration 74 | 75 | for i := 0; i < sizeData; i++ { 76 | elapsed := readFromJSON() 77 | jsonTimes[i] = elapsed 78 | 79 | elapsed = readFromPB() 80 | pbTimes[i] = elapsed 81 | } 82 | 83 | log.Printf("JSON: %fms", mean(jsonTimes)) 84 | log.Printf("PB: %fms", mean(pbTimes)) 85 | } 86 | -------------------------------------------------------------------------------- /chapter9/envoy/envoy.yaml: -------------------------------------------------------------------------------- 1 | node: 2 | id: todo-envoy-proxy 3 | cluster: grpc_cluster 4 | 5 | static_resources: 6 | listeners: 7 | - name: listener_grpc 8 | address: 9 | socket_address: 10 | address: 0.0.0.0 11 | port_value: 50051 12 | filter_chains: 13 | - filters: 14 | - name: envoy.filters.network.http_connection_manager 15 | typed_config: 16 | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager 17 | stat_prefix: listener_http 18 | http_filters: 19 | - name: envoy.filters.http.router 20 | typed_config: 21 | "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router 22 | route_config: 23 | name: route 24 | virtual_hosts: 25 | - name: vh 26 | domains: ["*"] 27 | routes: 28 | - match: 29 | prefix: /todo.v2.TodoService 30 | grpc: {} 31 | route: 32 | cluster: grpc_cluster 33 | transport_socket: 34 | name: envoy.transport_sockets.tls 35 | typed_config: 36 | "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext 37 | common_tls_context: 38 | tls_certificates: 39 | - certificate_chain: 40 | filename: ./certs/server_cert.pem 41 | private_key: 42 | filename: ./certs/server_key.pem 43 | 44 | clusters: 45 | - name: grpc_cluster 46 | type: STRICT_DNS 47 | http2_protocol_options: {} 48 | transport_socket: 49 | name: envoy.transport_sockets.tls 50 | typed_config: 51 | "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext 52 | lb_policy: round_robin 53 | load_assignment: 54 | cluster_name: grpc_cluster 55 | endpoints: 56 | - lb_endpoints: 57 | - endpoint: 58 | address: 59 | socket_address: 60 | address: "todo-server.default.svc.cluster.local" 61 | port_value: 50051 -------------------------------------------------------------------------------- /certs/ca_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 34 | -----END CERTIFICATE----- 35 | -------------------------------------------------------------------------------- /chapter7/certs/ca_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 34 | -----END CERTIFICATE----- 35 | -------------------------------------------------------------------------------- /chapter8/certs/ca_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIF6jCCA9KgAwIBAgIJANQvyb7tgLDkMA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNV 3 | BAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU1ZMMQ0wCwYDVQQKDARnUlBD 4 | MRcwFQYDVQQDDA50ZXN0LXNlcnZlcl9jYTAeFw0yMjAzMTgyMTQ0NTZaFw0zMjAz 5 | MTUyMTQ0NTZaMFAxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwD 6 | U1ZMMQ0wCwYDVQQKDARnUlBDMRcwFQYDVQQDDA50ZXN0LXNlcnZlcl9jYTCCAiIw 7 | DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANGmhBQQ5f3n4UhgJLsXHh3CE3ej 8 | Ox36ob+Hnny9Gb/OquA4FMKjTTaSrhKIQapqlCLODai50XKSRBJcgsvsqWk9UdL2 9 | 3zf7CzAPmg5CmzpWWwgpKPTuK5W+gLA1+uMKecBdH5gqSswQ3TD1fMfnJuq9mNfC 10 | GsMkplaqS5VATNFPVnqS7us3OXKEITmBaQP4wOpGP1PgqX7K08aZEeAyQJaTS5um 11 | 4MNlBLYa/nQ9Wca0Uk5tzoNjE6mWH7bTuwdoZgOIwKFmBbmsC9y/HzwV/zRsL8Yp 12 | +7FwfIYuZ5j8gBNqSFQjDFkm6Q7RcQ/lyHHj9YduOgTciIFVgx+j8aZvFqH127h8 13 | WIb7Jppy0DEDJE1hRP6iV2uVoaUxhXWrCWLBUU+naLix7SJ8rqw8gHwRNWfM/Lwg 14 | I3rGXdw5WIHVQcuxevN6qVSZeWVYAlAgfxjKtM5cKZyM+W80CSdVKEku1XA0sq6h 15 | jaiJdo6hpm8BLIB2k7LWafc5MASst7XULk4uDC/OYcEz3+C3Ryn1qBltr1gA3+5K 16 | ANuhjYCZH4P0pX08I1MpeVP6h8XhbBPEZg2txbVGlnDXEFoJN9Eg5iEKRBo/HKhf 17 | lP84ljtBSmCnsF6K/y3vnRiu+BVNP5KMq179DNqEy7tSygzgY41m3pSFojdvA59N 18 | JWJoy9/NZzdlU4nzAgMBAAGjgcYwgcMwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E 19 | FgQUW5AMXXg/zPSaLHwSO/7LwoBeZYUwgYAGA1UdIwR5MHeAFFuQDF14P8z0mix8 20 | Ejv+y8KAXmWFoVSkUjBQMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExDDAKBgNV 21 | BAcMA1NWTDENMAsGA1UECgwEZ1JQQzEXMBUGA1UEAwwOdGVzdC1zZXJ2ZXJfY2GC 22 | CQDUL8m+7YCw5DAOBgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADggIBAKTh 23 | Ofg4WospSN7Gg/q3bQqfSMT5XTFC7cj0j3cWDZBnmqb0HAFPmzHT+w3kBVNCyx1r 24 | iatOhaZRH7RA0vacZQT5pD2MGU48/zFfwBV/qHENQWuRLD2WOOEU3cjjoINBclfP 25 | im7ml/xgz0ACOgUyf+/2hkS7VLq4p9QQVGf2TQt65DZA9mUylZTdsBf4AfEg7IXv 26 | gaYpq6tYmNi7fXDzR/LT+fPd4ejQARy9U7uVhecyH9zTUMzm2Fr/p7HhydSXNwhF 27 | JUfPWw7XYO0lyA+8PxUSAKXOfsT44WNtHAeRm/Gkmn8inBdedFia/+M67k45b/wY 28 | RF11QzvaMR33jmrdZWxCc0Xjg8oZIP7T9MfGFULEGCpB3NY4YjnRrid/JZ/edhPR 29 | 2iOiEiek4qAaxeIne3CR2dqCM+n+FV1zCs4n3S0os4+kknnS5aNR5wZpqpZfG0Co 30 | FyWE+dE51cGcub1wT1oi5Xrxg/iRteCfd33Ky668FYKA/tHHdqkVfBflATU6iOtw 31 | dIzvFJk1H1mUwpJrH/aNOHzVCQ5KSpcc+kXcOQPafTHFB6zMVJ6O+Vm7SrqiSENM 32 | 2b1fBKxHIsxOtwrKuzbRhU5+eAICqwMd6gcIpT/JSR1r+UfHVcrXalbeazmT2DS5 33 | CFOeinj4WQvtPYOdbYsWg8Y9zGN4L9zH6GovM1wD 34 | -----END CERTIFICATE----- 35 | -------------------------------------------------------------------------------- /chapter9/certs/ca_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 34 | -----END CERTIFICATE----- 35 | -------------------------------------------------------------------------------- /chapter5/server/impl.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "time" 7 | 8 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1" 9 | ) 10 | 11 | // AddTask adds a Task to the database. 12 | // It returns the id of the newly inserted Task or an error. 13 | func (s *server) AddTask(_ context.Context, in *pb.AddTaskRequest) (*pb.AddTaskResponse, error) { 14 | id, _ := s.d.addTask(in.Description, in.DueDate.AsTime()) 15 | 16 | return &pb.AddTaskResponse{Id: id}, nil 17 | } 18 | 19 | // ListTasks streams the Tasks present in the database. 20 | // It optionally returns an error if anything went wrong. 21 | func (s *server) ListTasks(req *pb.ListTasksRequest, stream pb.TodoService_ListTasksServer) error { 22 | return s.d.getTasks(func(t interface{}) error { 23 | task := t.(*pb.Task) 24 | overdue := task.DueDate != nil && !task.Done && task.DueDate.AsTime().Before(time.Now().UTC()) 25 | err := stream.Send(&pb.ListTasksResponse{ 26 | Task: task, 27 | Overdue: overdue, 28 | }) 29 | 30 | return err 31 | }) 32 | } 33 | 34 | // UpdateTasks apply the updates needed to be made. 35 | // It reads the changes to be made through stream. 36 | // It optionally returns an error if anything went wrong. 37 | func (s *server) UpdateTasks(stream pb.TodoService_UpdateTasksServer) error { 38 | for { 39 | req, err := stream.Recv() 40 | 41 | if err == io.EOF { 42 | return stream.SendAndClose(&pb.UpdateTasksResponse{}) 43 | } 44 | 45 | if err != nil { 46 | return err 47 | } 48 | 49 | s.d.updateTask( 50 | req.Task.Id, 51 | req.Task.Description, 52 | req.Task.DueDate.AsTime(), 53 | req.Task.Done, 54 | ) 55 | } 56 | } 57 | 58 | // DeleteTasks deletes Tasks in the database. 59 | // It reads the changes to be made through stream. 60 | // For each change being applied it sends back an acknowledgement. 61 | // It optionally returns an error if anything went wrong. 62 | func (s *server) DeleteTasks(stream pb.TodoService_DeleteTasksServer) error { 63 | for { 64 | req, err := stream.Recv() 65 | 66 | if err == io.EOF { 67 | return nil 68 | } 69 | 70 | if err != nil { 71 | return err 72 | } 73 | 74 | s.d.deleteTask(req.Id) 75 | stream.Send(&pb.DeleteTasksResponse{}) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /chapter8/server/interceptors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/metadata" 10 | "google.golang.org/grpc/status" 11 | 12 | "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" 13 | ) 14 | 15 | const authTokenKey string = "auth_token" 16 | const authTokenValue string = "authd" 17 | 18 | // validateAuthToken asserts that the authTokenKey 19 | // is present and associated with authTokenValue 20 | // in the current context header. 21 | // It return a context if the auth token is valid, 22 | // otherwise it returns an error. 23 | func validateAuthToken(ctx context.Context) (context.Context, error) { 24 | md, _ := metadata.FromIncomingContext(ctx) 25 | 26 | if t, ok := md[authTokenKey]; ok { 27 | switch { 28 | case len(t) != 1: 29 | return nil, status.Errorf( 30 | codes.InvalidArgument, 31 | fmt.Sprintf("%s should contain only 1 value", authTokenKey), 32 | ) 33 | case t[0] != authTokenValue: 34 | return nil, status.Errorf( 35 | codes.Unauthenticated, 36 | fmt.Sprintf("incorrect %s", authTokenKey), 37 | ) 38 | } 39 | } else { 40 | return nil, status.Errorf( 41 | codes.Unauthenticated, 42 | fmt.Sprintf("failed to get %s", authTokenKey), 43 | ) 44 | } 45 | 46 | return ctx, nil 47 | } 48 | 49 | const grpcService = 5 // "grpc.service" 50 | const grpcMethod = 7 //"grpc.method" 51 | 52 | // logCalls logs the endpoints being called in a service. 53 | func logCalls(l *log.Logger) logging.Logger { 54 | return logging.LoggerFunc(func(_ context.Context, lvl logging.Level, msg string, fields ...any) { 55 | // f := make(map[string]any, len(fields)/2) 56 | // i := logging.Fields(fields).Iterator() 57 | 58 | // for i.Next() { 59 | // k, v := i.At() 60 | // f[k] = v 61 | // } 62 | 63 | switch lvl { 64 | case logging.LevelDebug: 65 | msg = fmt.Sprintf("DEBUG :%v", msg) 66 | case logging.LevelInfo: 67 | msg = fmt.Sprintf("INFO :%v", msg) 68 | case logging.LevelWarn: 69 | msg = fmt.Sprintf("WARN :%v", msg) 70 | case logging.LevelError: 71 | msg = fmt.Sprintf("ERROR :%v", msg) 72 | default: 73 | panic(fmt.Sprintf("unknown level %v", lvl)) 74 | } 75 | 76 | l.Println(msg, fields[grpcService], fields[grpcMethod]) 77 | //l.Println(msg, f[grpcService], f[grpcMethod]) 78 | }) 79 | } 80 | -------------------------------------------------------------------------------- /chapter9/server/interceptors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/metadata" 10 | "google.golang.org/grpc/status" 11 | 12 | "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" 13 | ) 14 | 15 | const authTokenKey string = "auth_token" 16 | const authTokenValue string = "authd" 17 | 18 | // validateAuthToken asserts that the authTokenKey 19 | // is present and associated with authTokenValue 20 | // in the current context header. 21 | // It return a context if the auth token is valid, 22 | // otherwise it returns an error. 23 | func validateAuthToken(ctx context.Context) (context.Context, error) { 24 | md, _ := metadata.FromIncomingContext(ctx) 25 | 26 | if t, ok := md[authTokenKey]; ok { 27 | switch { 28 | case len(t) != 1: 29 | return nil, status.Errorf( 30 | codes.InvalidArgument, 31 | fmt.Sprintf("%s should contain only 1 value", authTokenKey), 32 | ) 33 | case t[0] != authTokenValue: 34 | return nil, status.Errorf( 35 | codes.Unauthenticated, 36 | fmt.Sprintf("incorrect %s", authTokenKey), 37 | ) 38 | } 39 | } else { 40 | return nil, status.Errorf( 41 | codes.Unauthenticated, 42 | fmt.Sprintf("failed to get %s", authTokenKey), 43 | ) 44 | } 45 | 46 | return ctx, nil 47 | } 48 | 49 | const grpcService = 5 // "grpc.service" 50 | const grpcMethod = 7 //"grpc.method" 51 | 52 | // logCalls logs the endpoints being called in a service. 53 | func logCalls(l *log.Logger) logging.Logger { 54 | return logging.LoggerFunc(func(_ context.Context, lvl logging.Level, msg string, fields ...any) { 55 | // f := make(map[string]any, len(fields)/2) 56 | // i := logging.Fields(fields).Iterator() 57 | 58 | // for i.Next() { 59 | // k, v := i.At() 60 | // f[k] = v 61 | // } 62 | 63 | switch lvl { 64 | case logging.LevelDebug: 65 | msg = fmt.Sprintf("DEBUG :%v", msg) 66 | case logging.LevelInfo: 67 | msg = fmt.Sprintf("INFO :%v", msg) 68 | case logging.LevelWarn: 69 | msg = fmt.Sprintf("WARN :%v", msg) 70 | case logging.LevelError: 71 | msg = fmt.Sprintf("ERROR :%v", msg) 72 | default: 73 | panic(fmt.Sprintf("unknown level %v", lvl)) 74 | } 75 | 76 | l.Println(msg, fields[grpcService], fields[grpcMethod]) 77 | //l.Println(msg, f[grpcService], f[grpcMethod]) 78 | }) 79 | } 80 | -------------------------------------------------------------------------------- /chapter5/server/in_memory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v1" 8 | "google.golang.org/protobuf/types/known/timestamppb" 9 | ) 10 | 11 | // inMemoryDb is a fake database. 12 | // Its purpose is to let us focus on gRPC 13 | // and to not add any database dependencies such as ORM, ... 14 | type inMemoryDb struct { 15 | tasks []*pb.Task 16 | } 17 | 18 | // New creates a new instance of inMemoryDb 19 | func New() db { 20 | return &inMemoryDb{} 21 | } 22 | 23 | // addTask appends a Task, generated from description and dueDate, to the underlying array. 24 | // It never returns an error but a real database might! 25 | func (d *inMemoryDb) addTask(description string, dueDate time.Time) (uint64, error) { 26 | nextId := uint64(len(d.tasks) + 1) 27 | task := &pb.Task{ 28 | Id: nextId, 29 | Description: description, 30 | DueDate: timestamppb.New(dueDate), 31 | } 32 | 33 | d.tasks = append(d.tasks, task) 34 | return nextId, nil 35 | } 36 | 37 | // getTasks applies the function f to all the Tasks in the underlying array. 38 | // If any error happens, it will short circuit and return the error. 39 | func (d *inMemoryDb) getTasks(f func(interface{}) error) error { 40 | for _, task := range d.tasks { 41 | if err := f(task); err != nil { 42 | return err 43 | } 44 | } 45 | return nil 46 | } 47 | 48 | // updateTask applies an update of task to the first task that has the task.Id == id. 49 | // If a task is not found with the given id, it returns an error. 50 | func (d *inMemoryDb) updateTask(id uint64, description string, dueDate time.Time, done bool) error { 51 | for i, task := range d.tasks { 52 | if task.Id == id { 53 | t := d.tasks[i] 54 | t.Description = description 55 | t.DueDate = timestamppb.New(dueDate) 56 | t.Done = done 57 | return nil 58 | } 59 | } 60 | 61 | return fmt.Errorf("task with id %d not found", id) 62 | } 63 | 64 | // deleteTask deletes a task with task.Id == id in the underlying array. 65 | // If a task is not found with the given id, it returns an error. 66 | func (d *inMemoryDb) deleteTask(id uint64) error { 67 | for i, task := range d.tasks { 68 | if task.Id == id { 69 | d.tasks = append(d.tasks[:i], d.tasks[i+1:]...) 70 | return nil 71 | } 72 | } 73 | 74 | return fmt.Errorf("task with id %d not found", id) 75 | } 76 | -------------------------------------------------------------------------------- /chapter6/server/in_memory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 8 | "google.golang.org/protobuf/types/known/timestamppb" 9 | ) 10 | 11 | // inMemoryDb is a fake database. 12 | // Its purpose is to let us focus on gRPC 13 | // and to not add any database dependencies such as ORM, ... 14 | type inMemoryDb struct { 15 | tasks []*pb.Task 16 | } 17 | 18 | // New creates a new instance of inMemoryDb 19 | func New() db { 20 | return &inMemoryDb{} 21 | } 22 | 23 | // addTask appends a Task, generated from description and dueDate, to the underlying array. 24 | // It never returns an error but a real database might! 25 | func (d *inMemoryDb) addTask(description string, dueDate time.Time) (uint64, error) { 26 | nextId := uint64(len(d.tasks) + 1) 27 | task := &pb.Task{ 28 | Id: nextId, 29 | Description: description, 30 | DueDate: timestamppb.New(dueDate), 31 | } 32 | 33 | d.tasks = append(d.tasks, task) 34 | return nextId, nil 35 | } 36 | 37 | // getTasks applies the function f to all the Tasks in the underlying array. 38 | // If any error happens, it will short circuit and return the error. 39 | func (d *inMemoryDb) getTasks(f func(interface{}) error) error { 40 | for _, task := range d.tasks { 41 | if err := f(task); err != nil { 42 | return err 43 | } 44 | } 45 | return nil 46 | } 47 | 48 | // updateTask applies an update of task to the first task that has the task.Id == id. 49 | // If a task is not found with the given id, it returns an error. 50 | func (d *inMemoryDb) updateTask(id uint64, description string, dueDate time.Time, done bool) error { 51 | for i, task := range d.tasks { 52 | if task.Id == id { 53 | t := d.tasks[i] 54 | t.Description = description 55 | t.DueDate = timestamppb.New(dueDate) 56 | t.Done = done 57 | return nil 58 | } 59 | } 60 | 61 | return fmt.Errorf("task with id %d not found", id) 62 | } 63 | 64 | // deleteTask deletes a task with task.Id == id in the underlying array. 65 | // If a task is not found with the given id, it returns an error. 66 | func (d *inMemoryDb) deleteTask(id uint64) error { 67 | for i, task := range d.tasks { 68 | if task.Id == id { 69 | d.tasks = append(d.tasks[:i], d.tasks[i+1:]...) 70 | return nil 71 | } 72 | } 73 | 74 | return fmt.Errorf("task with id %d not found", id) 75 | } 76 | -------------------------------------------------------------------------------- /chapter7/server/in_memory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 8 | "google.golang.org/protobuf/types/known/timestamppb" 9 | ) 10 | 11 | // inMemoryDb is a fake database. 12 | // Its purpose is to let us focus on gRPC 13 | // and to not add any database dependencies such as ORM, ... 14 | type inMemoryDb struct { 15 | tasks []*pb.Task 16 | } 17 | 18 | // New creates a new instance of inMemoryDb 19 | func New() db { 20 | return &inMemoryDb{} 21 | } 22 | 23 | // addTask appends a Task, generated from description and dueDate, to the underlying array. 24 | // It never returns an error but a real database might! 25 | func (d *inMemoryDb) addTask(description string, dueDate time.Time) (uint64, error) { 26 | nextId := uint64(len(d.tasks) + 1) 27 | task := &pb.Task{ 28 | Id: nextId, 29 | Description: description, 30 | DueDate: timestamppb.New(dueDate), 31 | } 32 | 33 | d.tasks = append(d.tasks, task) 34 | return nextId, nil 35 | } 36 | 37 | // getTasks applies the function f to all the Tasks in the underlying array. 38 | // If any error happens, it will short circuit and return the error. 39 | func (d *inMemoryDb) getTasks(f func(interface{}) error) error { 40 | for _, task := range d.tasks { 41 | if err := f(task); err != nil { 42 | return err 43 | } 44 | } 45 | return nil 46 | } 47 | 48 | // updateTask applies an update of task to the first task that has the task.Id == id. 49 | // If a task is not found with the given id, it returns an error. 50 | func (d *inMemoryDb) updateTask(id uint64, description string, dueDate time.Time, done bool) error { 51 | for i, task := range d.tasks { 52 | if task.Id == id { 53 | t := d.tasks[i] 54 | t.Description = description 55 | t.DueDate = timestamppb.New(dueDate) 56 | t.Done = done 57 | return nil 58 | } 59 | } 60 | 61 | return fmt.Errorf("task with id %d not found", id) 62 | } 63 | 64 | // deleteTask deletes a task with task.Id == id in the underlying array. 65 | // If a task is not found with the given id, it returns an error. 66 | func (d *inMemoryDb) deleteTask(id uint64) error { 67 | for i, task := range d.tasks { 68 | if task.Id == id { 69 | d.tasks = append(d.tasks[:i], d.tasks[i+1:]...) 70 | return nil 71 | } 72 | } 73 | 74 | return fmt.Errorf("task with id %d not found", id) 75 | } 76 | -------------------------------------------------------------------------------- /chapter8/server/in_memory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 8 | "google.golang.org/protobuf/types/known/timestamppb" 9 | ) 10 | 11 | // inMemoryDb is a fake database. 12 | // Its purpose is to let us focus on gRPC 13 | // and to not add any database dependencies such as ORM, ... 14 | type inMemoryDb struct { 15 | tasks []*pb.Task 16 | } 17 | 18 | // New creates a new instance of inMemoryDb 19 | func New() db { 20 | return &inMemoryDb{} 21 | } 22 | 23 | // addTask appends a Task, generated from description and dueDate, to the underlying array. 24 | // It never returns an error but a real database might! 25 | func (d *inMemoryDb) addTask(description string, dueDate time.Time) (uint64, error) { 26 | nextId := uint64(len(d.tasks) + 1) 27 | task := &pb.Task{ 28 | Id: nextId, 29 | Description: description, 30 | DueDate: timestamppb.New(dueDate), 31 | } 32 | 33 | d.tasks = append(d.tasks, task) 34 | return nextId, nil 35 | } 36 | 37 | // getTasks applies the function f to all the Tasks in the underlying array. 38 | // If any error happens, it will short circuit and return the error. 39 | func (d *inMemoryDb) getTasks(f func(interface{}) error) error { 40 | for _, task := range d.tasks { 41 | if err := f(task); err != nil { 42 | return err 43 | } 44 | } 45 | return nil 46 | } 47 | 48 | // updateTask applies an update of task to the first task that has the task.Id == id. 49 | // If a task is not found with the given id, it returns an error. 50 | func (d *inMemoryDb) updateTask(id uint64, description string, dueDate time.Time, done bool) error { 51 | for i, task := range d.tasks { 52 | if task.Id == id { 53 | t := d.tasks[i] 54 | t.Description = description 55 | t.DueDate = timestamppb.New(dueDate) 56 | t.Done = done 57 | return nil 58 | } 59 | } 60 | 61 | return fmt.Errorf("task with id %d not found", id) 62 | } 63 | 64 | // deleteTask deletes a task with task.Id == id in the underlying array. 65 | // If a task is not found with the given id, it returns an error. 66 | func (d *inMemoryDb) deleteTask(id uint64) error { 67 | for i, task := range d.tasks { 68 | if task.Id == id { 69 | d.tasks = append(d.tasks[:i], d.tasks[i+1:]...) 70 | return nil 71 | } 72 | } 73 | 74 | return fmt.Errorf("task with id %d not found", id) 75 | } 76 | -------------------------------------------------------------------------------- /chapter9/server/in_memory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | pb "github.com/PacktPublishing/gRPC-Go-for-Professionals/proto/todo/v2" 8 | "google.golang.org/protobuf/types/known/timestamppb" 9 | ) 10 | 11 | // inMemoryDb is a fake database. 12 | // Its purpose is to let us focus on gRPC 13 | // and to not add any database dependencies such as ORM, ... 14 | type inMemoryDb struct { 15 | tasks []*pb.Task 16 | } 17 | 18 | // New creates a new instance of inMemoryDb 19 | func New() db { 20 | return &inMemoryDb{} 21 | } 22 | 23 | // addTask appends a Task, generated from description and dueDate, to the underlying array. 24 | // It never returns an error but a real database might! 25 | func (d *inMemoryDb) addTask(description string, dueDate time.Time) (uint64, error) { 26 | nextId := uint64(len(d.tasks) + 1) 27 | task := &pb.Task{ 28 | Id: nextId, 29 | Description: description, 30 | DueDate: timestamppb.New(dueDate), 31 | } 32 | 33 | d.tasks = append(d.tasks, task) 34 | return nextId, nil 35 | } 36 | 37 | // getTasks applies the function f to all the Tasks in the underlying array. 38 | // If any error happens, it will short circuit and return the error. 39 | func (d *inMemoryDb) getTasks(f func(interface{}) error) error { 40 | for _, task := range d.tasks { 41 | if err := f(task); err != nil { 42 | return err 43 | } 44 | } 45 | return nil 46 | } 47 | 48 | // updateTask applies an update of task to the first task that has the task.Id == id. 49 | // If a task is not found with the given id, it returns an error. 50 | func (d *inMemoryDb) updateTask(id uint64, description string, dueDate time.Time, done bool) error { 51 | for i, task := range d.tasks { 52 | if task.Id == id { 53 | t := d.tasks[i] 54 | t.Description = description 55 | t.DueDate = timestamppb.New(dueDate) 56 | t.Done = done 57 | return nil 58 | } 59 | } 60 | 61 | return fmt.Errorf("task with id %d not found", id) 62 | } 63 | 64 | // deleteTask deletes a task with task.Id == id in the underlying array. 65 | // If a task is not found with the given id, it returns an error. 66 | func (d *inMemoryDb) deleteTask(id uint64) error { 67 | for i, task := range d.tasks { 68 | if task.Id == id { 69 | d.tasks = append(d.tasks[:i], d.tasks[i+1:]...) 70 | return nil 71 | } 72 | } 73 | 74 | return fmt.Errorf("task with id %d not found", id) 75 | } 76 | -------------------------------------------------------------------------------- /chapter8/client/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= 4 | github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= 5 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 6 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 7 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= 8 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= 9 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 10 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 11 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 12 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 13 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 14 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 15 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 16 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 17 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 18 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 19 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 20 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 21 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 22 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 23 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 24 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 25 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 26 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 27 | -------------------------------------------------------------------------------- /chapter9/client/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= 4 | github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= 5 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 6 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 7 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= 8 | github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= 9 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 10 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 11 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 12 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 13 | golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= 14 | golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 15 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= 16 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 17 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 18 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 19 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= 20 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 21 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 22 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 23 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 24 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 25 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 26 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 27 | -------------------------------------------------------------------------------- /chapter9/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 9 - Production-Grade APIs 2 | 3 | > This is based on the work done in chapter8 folder. 4 | 5 | This folders shows how to unit and load test, and how to deploy your microservice on k8s. The main code for the implementations can be found in the following files: 6 | 7 | - [server/server_test.go](server/server_test.go) 8 | - [server/impl_test.go](server/impl_test.go) 9 | - [server/Dockerfile](server/Dockerfile) 10 | - [k8s/server.yaml](k8s/server.yaml) 11 | - [envoy/Dockerfile](envoy/Dockerfile) 12 | - [envoy/envoy.yaml](envoy/envoy.yaml) 13 | - [envoy/service.yaml](envoy/service.yaml) 14 | - [envoy/deployment.yaml](envoy/deployment.yaml) 15 | 16 | ## Running the code 17 | 18 | ### Server 19 | 20 | ```shell 21 | $ go test ./server 22 | ``` 23 | 24 | ### Docker (Server) 25 | 26 | ```shell 27 | $ docker buildx create --name mybuild --driver=docker-container 28 | $ docker buildx build \ 29 | --tag clementjean/grpc-go-packt-book:server \ 30 | --file server/Dockerfile \ 31 | --platform linux/arm64 \ # choose your platform 32 | --builder mybuild \ 33 | --load . 34 | $ docker image ls 35 | REPOSITORY TAG SIZE 36 | clementjean/grpc-go-packt-book server 10.9MB 37 | ``` 38 | 39 | ### Docker (Envoy) 40 | 41 | ```shell 42 | $ docker buildx create --name mybuild --driver=docker-container # if needed 43 | $ docker buildx build \ 44 | --tag clementjean/grpc-go-packt-book:envoy-proxy \ 45 | --file server/Dockerfile \ 46 | --platform linux/arm64 \ # choose your platform 47 | --builder mybuild \ 48 | --load . 49 | REPOSITORY TAG SIZE 50 | clementjean/grpc-go-packt-book envoy-proxy 77.1MB 51 | ``` 52 | 53 | ### Kind 54 | 55 | If you use [Kind](https://kind.sigs.k8s.io/) for your cluster, you can run the following command to spin up a 3 node cluster: 56 | 57 | ```shell 58 | $ kind create cluster --config k8s/kind.yaml 59 | ``` 60 | 61 | ### Kubernetes 62 | 63 | ```shell 64 | $ kubectl apply -f k8s/server.yaml 65 | $ kubectl apply -f envoy/service.yaml 66 | $ kubectl apply -f envoy/deployment.yaml 67 | ``` 68 | 69 | If you need to port-forward, you can run: 70 | 71 | ```shell 72 | $ kubectl get pods 73 | NAME READY STATUS 74 | todo-envoy-$HASH 1/1 Running 75 | #... 76 | $ kubectl port-forward pod/todo-envoy-$HASH 50051 77 | ``` 78 | 79 | Then you should be able to run the client against the port 50051. -------------------------------------------------------------------------------- /chapter7/server/interceptors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | 8 | "google.golang.org/grpc" 9 | "google.golang.org/grpc/codes" 10 | "google.golang.org/grpc/metadata" 11 | "google.golang.org/grpc/status" 12 | ) 13 | 14 | const authTokenKey string = "auth_token" 15 | const authTokenValue string = "authd" 16 | 17 | // validateAuthToken asserts that the authTokenKey 18 | // is present and associated with authTokenValue 19 | // in the current context header. 20 | func validateAuthToken(ctx context.Context) error { 21 | md, _ := metadata.FromIncomingContext(ctx) 22 | 23 | if t, ok := md[authTokenKey]; ok { 24 | switch { 25 | case len(t) != 1: 26 | return status.Errorf( 27 | codes.InvalidArgument, 28 | fmt.Sprintf("%s should contain only 1 value", authTokenKey), 29 | ) 30 | case t[0] != authTokenValue: 31 | return status.Errorf( 32 | codes.Unauthenticated, 33 | fmt.Sprintf("incorrect %s", authTokenKey), 34 | ) 35 | } 36 | } else { 37 | return status.Errorf( 38 | codes.Unauthenticated, 39 | fmt.Sprintf("failed to get %s", authTokenKey), 40 | ) 41 | } 42 | 43 | return nil 44 | } 45 | 46 | // unaryAuthInterceptor calls validateAuthToken to determine wether to 47 | // continue with the current call or not. 48 | func unaryAuthInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 49 | if err := validateAuthToken(ctx); err != nil { 50 | return nil, err 51 | } 52 | 53 | return handler(ctx, req) 54 | } 55 | 56 | // streamAuthInterceptor calls validateAuthToken to determine wether to 57 | // continue with the current call or not. 58 | func streamAuthInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { 59 | if err := validateAuthToken(ss.Context()); err != nil { 60 | return err 61 | } 62 | 63 | return handler(srv, ss) 64 | } 65 | 66 | // unaryLogInterceptor logs the endpoints being called. 67 | func unaryLogInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 68 | log.Println(info.FullMethod, "called") 69 | return handler(ctx, req) 70 | } 71 | 72 | // streamLogInterceptor logs the endpoints being called. 73 | func streamLogInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { 74 | log.Println(info.FullMethod, "called") 75 | return handler(srv, ss) 76 | } 77 | -------------------------------------------------------------------------------- /chapter9/WORKSPACE.bazel: -------------------------------------------------------------------------------- 1 | workspace(name = "github_com_packtpublishing_grpc_go_for_professionals") 2 | 3 | load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") 4 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 5 | load( 6 | "//:versions.bzl", 7 | "GAZELLE_SHA256", 8 | "GAZELLE_VERSION", 9 | "GO_VERSION", 10 | "PROTOC_GEN_VALIDATE_VERSION", 11 | "PROTO_VERSION", 12 | "RULES_GO_SHA256", 13 | "RULES_GO_VERSION", 14 | ) 15 | 16 | # Rules_go 17 | http_archive( 18 | name = "io_bazel_rules_go", 19 | sha256 = RULES_GO_SHA256, 20 | urls = [ 21 | "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/%s/rules_go-%s.zip" % (RULES_GO_VERSION, RULES_GO_VERSION), 22 | "https://github.com/bazelbuild/rules_go/releases/download/%s/rules_go-%s.zip" % (RULES_GO_VERSION, RULES_GO_VERSION), 23 | ], 24 | ) 25 | 26 | # Gazelle 27 | http_archive( 28 | name = "bazel_gazelle", 29 | sha256 = GAZELLE_SHA256, 30 | urls = [ 31 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/%s/bazel-gazelle-%s.tar.gz" % (GAZELLE_VERSION, GAZELLE_VERSION), 32 | "https://github.com/bazelbuild/bazel-gazelle/releases/download/%s/bazel-gazelle-%s.tar.gz" % (GAZELLE_VERSION, GAZELLE_VERSION), 33 | ], 34 | ) 35 | 36 | load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") 37 | load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") 38 | load("//:deps.bzl", "go_dependencies") 39 | 40 | # gazelle:repository_macro deps.bzl%go_dependencies 41 | go_dependencies() 42 | 43 | go_rules_dependencies() 44 | 45 | go_register_toolchains(version = GO_VERSION) 46 | 47 | gazelle_dependencies(go_repository_default_config = "//:WORKSPACE.bazel") 48 | 49 | # Protobuf 50 | git_repository( 51 | name = "com_google_protobuf", 52 | remote = "https://github.com/protocolbuffers/protobuf", 53 | tag = PROTO_VERSION, 54 | ) 55 | 56 | load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") 57 | 58 | protobuf_deps() 59 | 60 | # protoc-gen-validate 61 | git_repository( 62 | name = "com_envoyproxy_protoc_gen_validate", 63 | remote = "https://github.com/bufbuild/protoc-gen-validate", 64 | tag = PROTOC_GEN_VALIDATE_VERSION, 65 | ) 66 | 67 | load("@com_envoyproxy_protoc_gen_validate//bazel:repositories.bzl", "pgv_dependencies") 68 | 69 | pgv_dependencies() 70 | 71 | load("@com_envoyproxy_protoc_gen_validate//:dependencies.bzl", "go_third_party") 72 | 73 | go_third_party() 74 | -------------------------------------------------------------------------------- /WORKSPACE.bazel: -------------------------------------------------------------------------------- 1 | workspace(name = "github_com_packtpublishing_grpc_go_for_professionals") 2 | 3 | load( 4 | "//:versions.bzl", 5 | "GAZELLE_SHA256", 6 | "GAZELLE_VERSION", 7 | "GO_VERSION", 8 | "PROTOC_GEN_VALIDATE_VERSION", 9 | "PROTO_VERSION", 10 | "RULES_GO_SHA256", 11 | "RULES_GO_VERSION", 12 | ) 13 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 14 | load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") 15 | 16 | # Rules_go 17 | http_archive( 18 | name = "io_bazel_rules_go", 19 | sha256 = RULES_GO_SHA256, 20 | urls = [ 21 | "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/%s/rules_go-%s.zip" % (RULES_GO_VERSION, RULES_GO_VERSION), 22 | "https://github.com/bazelbuild/rules_go/releases/download/%s/rules_go-%s.zip" % (RULES_GO_VERSION, RULES_GO_VERSION), 23 | ], 24 | ) 25 | 26 | # Gazelle 27 | http_archive( 28 | name = "bazel_gazelle", 29 | sha256 = GAZELLE_SHA256, 30 | urls = [ 31 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/%s/bazel-gazelle-%s.tar.gz" % (GAZELLE_VERSION, GAZELLE_VERSION), 32 | "https://github.com/bazelbuild/bazel-gazelle/releases/download/%s/bazel-gazelle-%s.tar.gz" % (GAZELLE_VERSION, GAZELLE_VERSION), 33 | ], 34 | ) 35 | 36 | load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") 37 | load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") 38 | load("//:deps.bzl", "go_dependencies") 39 | 40 | # gazelle:repository_macro deps.bzl%go_dependencies 41 | go_dependencies() 42 | 43 | go_rules_dependencies() 44 | 45 | go_register_toolchains(version = GO_VERSION) 46 | 47 | gazelle_dependencies(go_repository_default_config = "//:WORKSPACE.bazel") 48 | 49 | # Protobuf 50 | git_repository( 51 | name = "com_google_protobuf", 52 | remote = "https://github.com/protocolbuffers/protobuf", 53 | tag = PROTO_VERSION, 54 | ) 55 | 56 | load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") 57 | 58 | protobuf_deps() 59 | 60 | # protoc-gen-validate 61 | git_repository( 62 | name = "com_envoyproxy_protoc_gen_validate", 63 | remote = "https://github.com/bufbuild/protoc-gen-validate", 64 | tag = PROTOC_GEN_VALIDATE_VERSION, 65 | ) 66 | 67 | load("@com_envoyproxy_protoc_gen_validate//bazel:repositories.bzl", "pgv_dependencies") 68 | load("@com_envoyproxy_protoc_gen_validate//:dependencies.bzl", "go_third_party") 69 | 70 | pgv_dependencies() 71 | 72 | # gazelle:repository_macro deps.bzl%go_third_party 73 | go_third_party() 74 | --------------------------------------------------------------------------------