├── ex-1-connection ├── sqlite.db ├── main.go ├── README.md └── solution │ └── main.go ├── ex-3-streaming ├── solution │ ├── data-streamer │ │ ├── sqlite.db │ │ ├── database │ │ │ └── sqlite.go │ │ └── main.go │ └── main.go ├── main.go └── README.md ├── ex-4-data-contracts ├── buf.gen.yaml ├── buf.lock ├── buf.yaml ├── server.go ├── proto │ └── user.proto ├── README.md ├── solution │ ├── server.go │ └── server_test.go ├── server_test.go └── gen │ └── go │ └── proto │ ├── user_grpc.pb.go │ └── user.pb.go ├── database-demo ├── sqlc.yaml ├── queries │ └── user.sql ├── database │ ├── db.go │ ├── models.go │ └── user.sql.go ├── migrations │ └── 0001_game_create.sql └── main.go ├── grpc-gateway-demo ├── buf.gen.yaml ├── buf.lock ├── buf.yaml ├── main.go ├── proto │ └── user.proto ├── server │ ├── server.go │ └── server_test.go └── gen │ └── proto │ ├── user_grpc.pb.go │ ├── user.pb.go │ └── user.pb.gw.go ├── ex-2-mocking-db-tests ├── README.md ├── server.go ├── solution │ ├── server.go │ └── server_test.go └── server_test.go ├── .gitignore ├── go.mod ├── LICENSE ├── README.md └── go.sum /ex-1-connection/sqlite.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soypete/Golang_datatools_exercises/HEAD/ex-1-connection/sqlite.db -------------------------------------------------------------------------------- /ex-3-streaming/solution/data-streamer/sqlite.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soypete/Golang_datatools_exercises/HEAD/ex-3-streaming/solution/data-streamer/sqlite.db -------------------------------------------------------------------------------- /ex-4-data-contracts/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: gen/go 5 | opt: paths=source_relative 6 | - plugin: go-grpc 7 | out: gen/go 8 | opt: paths=source_relative,require_unimplemented_servers=false 9 | -------------------------------------------------------------------------------- /database-demo/sqlc.yaml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | sql: 3 | - engine: "postgresql" 4 | queries: "queries/user.sql" 5 | schema: "migrations/0001_game_create.sql" 6 | gen: 7 | go: 8 | package: "database" 9 | out: "database" 10 | -------------------------------------------------------------------------------- /database-demo/queries/user.sql: -------------------------------------------------------------------------------- 1 | -- name: GetUser :one 2 | SELECT * FROM users 3 | WHERE username = $1; 4 | 5 | -- name: UpdateUser :exec 6 | INSERT INTO users 7 | (username) VALUES ($1) 8 | ON CONFLICT (username) 9 | DO NOTHING; 10 | 11 | -- name: DeleteUser :exec 12 | DELETE FROM users 13 | WHERE username = $1; 14 | 15 | -------------------------------------------------------------------------------- /grpc-gateway-demo/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - plugin: go 4 | out: gen 5 | opt: paths=source_relative 6 | - plugin: go-grpc 7 | out: gen 8 | opt: paths=source_relative,require_unimplemented_servers=false 9 | - name: grpc-gateway 10 | out: gen 11 | opt: paths=source_relative 12 | -------------------------------------------------------------------------------- /ex-1-connection/main.go: -------------------------------------------------------------------------------- 1 | // to run postgres locally, you can use docker 2 | // docker pull postgres 3 | // docker run --name postgres -e POSTGRES_PASSWORD=postgres -p 5431:5431 -d postgres 4 | // 5 | // otherwise use the sqlite provided in the repo 6 | 7 | package main 8 | 9 | // add driver here 10 | 11 | func main() { 12 | connectionString := "/sqlite.db" 13 | // TODO: connect to sqlite database here 14 | 15 | // TODO: query the database here 16 | db.Close() 17 | } 18 | -------------------------------------------------------------------------------- /ex-2-mocking-db-tests/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 2 - writing tests with a Data store 2 | 3 | I/O operations are cumbersome and should be avoided in unit tests. When you are building service that rely on database conenctions this makes writing unit tests and maintaining good test coverage cumbersome. Using the provided [server.go](/server.go) and [server_test.go](/server_test.go) add mock functions that that emulate the database layer. You should add mock fuctions to replicate one successful db response and one failed db response. 4 | 5 | Solution [here](/solution/server_test.go) 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ 19 | 20 | # Go workspace file 21 | go.work 22 | -------------------------------------------------------------------------------- /ex-4-data-contracts/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: googleapis 6 | repository: googleapis 7 | commit: 28151c0d0a1641bf938a7672c500e01d 8 | digest: shake256:49215edf8ef57f7863004539deff8834cfb2195113f0b890dd1f67815d9353e28e668019165b9d872395871eeafcbab3ccfdb2b5f11734d3cca95be9e8d139de 9 | - remote: buf.build 10 | owner: grpc-ecosystem 11 | repository: grpc-gateway 12 | commit: 3f42134f4c564983838425bc43c7a65f 13 | digest: shake256:3d11d4c0fe5e05fda0131afefbce233940e27f0c31c5d4e385686aea58ccd30f72053f61af432fa83f1fc11cda57f5f18ca3da26a29064f73c5a0d076bba8d92 14 | -------------------------------------------------------------------------------- /grpc-gateway-demo/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: googleapis 6 | repository: googleapis 7 | commit: 28151c0d0a1641bf938a7672c500e01d 8 | digest: shake256:49215edf8ef57f7863004539deff8834cfb2195113f0b890dd1f67815d9353e28e668019165b9d872395871eeafcbab3ccfdb2b5f11734d3cca95be9e8d139de 9 | - remote: buf.build 10 | owner: grpc-ecosystem 11 | repository: grpc-gateway 12 | commit: 3f42134f4c564983838425bc43c7a65f 13 | digest: shake256:3d11d4c0fe5e05fda0131afefbce233940e27f0c31c5d4e385686aea58ccd30f72053f61af432fa83f1fc11cda57f5f18ca3da26a29064f73c5a0d076bba8d92 14 | -------------------------------------------------------------------------------- /database-demo/database/db.go: -------------------------------------------------------------------------------- 1 | // Code generated by sqlc. DO NOT EDIT. 2 | // versions: 3 | // sqlc v1.18.0 4 | 5 | package database 6 | 7 | import ( 8 | "context" 9 | "database/sql" 10 | ) 11 | 12 | type DBTX interface { 13 | ExecContext(context.Context, string, ...interface{}) (sql.Result, error) 14 | PrepareContext(context.Context, string) (*sql.Stmt, error) 15 | QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) 16 | QueryRowContext(context.Context, string, ...interface{}) *sql.Row 17 | } 18 | 19 | func New(db DBTX) *Queries { 20 | return &Queries{db: db} 21 | } 22 | 23 | type Queries struct { 24 | db DBTX 25 | } 26 | 27 | func (q *Queries) WithTx(tx *sql.Tx) *Queries { 28 | return &Queries{ 29 | db: tx, 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database-demo/database/models.go: -------------------------------------------------------------------------------- 1 | // Code generated by sqlc. DO NOT EDIT. 2 | // versions: 3 | // sqlc v1.18.0 4 | 5 | package database 6 | 7 | import ( 8 | "database/sql" 9 | "time" 10 | ) 11 | 12 | type Game struct { 13 | ID int32 14 | Host string 15 | Players []string 16 | Answer string 17 | Questions []string 18 | Guesses []string 19 | StartTime time.Time 20 | EndTime sql.NullTime 21 | Ended sql.NullBool 22 | } 23 | 24 | type Guess struct { 25 | ID int32 26 | Guess string 27 | UserID int32 28 | GameID int32 29 | Correct sql.NullBool 30 | } 31 | 32 | type Question struct { 33 | ID int32 34 | Question string 35 | UserID int32 36 | GameID int32 37 | } 38 | 39 | type User struct { 40 | ID int32 41 | Username string 42 | CreatedAt time.Time 43 | } 44 | -------------------------------------------------------------------------------- /grpc-gateway-demo/buf.yaml: -------------------------------------------------------------------------------- 1 | # Below is not the lint and breaking configuration we recommend! 2 | # This just just what googleapis passes. 3 | # For lint, we recommend having the single value "DEFAULT" in "use" 4 | # with no values in "except". 5 | # For breaking, we recommend having the single value "FILE" in use. 6 | # See https://docs.buf.build/lint-usage 7 | # See https://docs.buf.build/breaking-usage 8 | version: v1beta1 9 | name: buf.build/soypete/Golang_datatools_exercises 10 | deps: 11 | - buf.build/googleapis/googleapis 12 | - buf.build/grpc-ecosystem/grpc-gateway 13 | lint: 14 | use: 15 | - BASIC 16 | except: 17 | - ENUM_NO_ALLOW_ALIAS 18 | - IMPORT_NO_PUBLIC 19 | - PACKAGE_AFFINITY 20 | - PACKAGE_DIRECTORY_MATCH 21 | - PACKAGE_SAME_DIRECTORY 22 | breaking: 23 | use: 24 | - WIRE_JSON 25 | -------------------------------------------------------------------------------- /ex-4-data-contracts/buf.yaml: -------------------------------------------------------------------------------- 1 | # Below is not the lint and breaking configuration we recommend! 2 | # This just just what googleapis passes. 3 | # For lint, we recommend having the single value "DEFAULT" in "use" 4 | # with no values in "except". 5 | # For breaking, we recommend having the single value "FILE" in use. 6 | # See https://docs.buf.build/lint-usage 7 | # See https://docs.buf.build/breaking-usage 8 | version: v1beta1 9 | name: buf.build/soypete/Golang_datatools_exercises 10 | deps: 11 | - buf.build/googleapis/googleapis 12 | - buf.build/grpc-ecosystem/grpc-gateway 13 | # build: 14 | # roots: 15 | # - proto 16 | lint: 17 | use: 18 | - BASIC 19 | except: 20 | - ENUM_NO_ALLOW_ALIAS 21 | - IMPORT_NO_PUBLIC 22 | - PACKAGE_AFFINITY 23 | - PACKAGE_DIRECTORY_MATCH 24 | - PACKAGE_SAME_DIRECTORY 25 | breaking: 26 | use: 27 | - WIRE_JSON 28 | -------------------------------------------------------------------------------- /ex-4-data-contracts/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | 6 | gengo "github.com/soypete/Golang_datatools_exercises/ex-4-data-contracts/gen/go/proto" 7 | "google.golang.org/protobuf/types/known/emptypb" 8 | ) 9 | 10 | type Server struct { 11 | gengo.UnimplementedUserActionServer 12 | } 13 | 14 | func setupServer() *Server { 15 | return &Server{} 16 | } 17 | 18 | func (s *Server) Close(ctx context.Context) error { 19 | ctx.Done() 20 | return nil 21 | } 22 | 23 | func (s *Server) UpdateUser(ctx context.Context, in *gengo.User) (*emptypb.Empty, error) { 24 | return nil, nil 25 | } 26 | 27 | func (s *Server) GetUserInfo(ctx context.Context, in *gengo.UserIdentifier) (*gengo.User, error) { 28 | return nil, nil 29 | } 30 | 31 | func (s *Server) DeleteUser(ctx context.Context, in *gengo.UserIdentifier) (*emptypb.Empty, error) { 32 | return nil, nil 33 | } 34 | 35 | func (s *Server) SendUserAction(ctx context.Context, in *gengo.Action) (*emptypb.Empty, error) { 36 | return nil, nil 37 | } 38 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/soypete/Golang_datatools_exercises 2 | 3 | go 1.21.3 4 | 5 | require ( 6 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 7 | github.com/mattn/go-sqlite3 v1.14.17 8 | github.com/nats-io/nats.go v1.31.0 9 | github.com/pressly/goose/v3 v3.15.1 10 | github.com/soypete/WebServices-in-3-weeks v0.0.0-20231015040516-f9017a42446c 11 | google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d 12 | google.golang.org/grpc v1.59.0 13 | google.golang.org/protobuf v1.31.0 14 | ) 15 | 16 | require ( 17 | github.com/golang/protobuf v1.5.3 // indirect 18 | github.com/klauspost/compress v1.17.0 // indirect 19 | github.com/nats-io/nkeys v0.4.6 // indirect 20 | github.com/nats-io/nuid v1.0.1 // indirect 21 | golang.org/x/crypto v0.14.0 // indirect 22 | golang.org/x/net v0.17.0 // indirect 23 | golang.org/x/sys v0.13.0 // indirect 24 | golang.org/x/text v0.13.0 // indirect 25 | google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect 26 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect 27 | ) 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Miriah Peterson 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 | -------------------------------------------------------------------------------- /database-demo/database/user.sql.go: -------------------------------------------------------------------------------- 1 | // Code generated by sqlc. DO NOT EDIT. 2 | // versions: 3 | // sqlc v1.18.0 4 | // source: user.sql 5 | 6 | package database 7 | 8 | import ( 9 | "context" 10 | ) 11 | 12 | const deleteUser = `-- name: DeleteUser :exec 13 | DELETE FROM users 14 | WHERE username = $1 15 | ` 16 | 17 | func (q *Queries) DeleteUser(ctx context.Context, username string) error { 18 | _, err := q.db.ExecContext(ctx, deleteUser, username) 19 | return err 20 | } 21 | 22 | const getUser = `-- name: GetUser :one 23 | SELECT id, username, created_at FROM users 24 | WHERE username = $1 25 | ` 26 | 27 | func (q *Queries) GetUser(ctx context.Context, username string) (User, error) { 28 | row := q.db.QueryRowContext(ctx, getUser, username) 29 | var i User 30 | err := row.Scan(&i.ID, &i.Username, &i.CreatedAt) 31 | return i, err 32 | } 33 | 34 | const updateUser = `-- name: UpdateUser :exec 35 | INSERT INTO users 36 | (username) VALUES ($1) 37 | ON CONFLICT (username) 38 | DO NOTHING 39 | ` 40 | 41 | func (q *Queries) UpdateUser(ctx context.Context, username string) error { 42 | _, err := q.db.ExecContext(ctx, updateUser, username) 43 | return err 44 | } 45 | -------------------------------------------------------------------------------- /ex-4-data-contracts/proto/user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package user; 3 | 4 | import "google/protobuf/empty.proto"; 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | option go_package = "github.com/Soypete/Golang_datatools_exercises/ex-4-data-contracts/proto/gen/go"; 8 | 9 | service UserAction { 10 | rpc UpdateUser(User) returns (google.protobuf.Empty) {} 11 | rpc GetUserInfo(UserIdentifier) returns (User) {} 12 | rpc DeleteUser(UserIdentifier) returns (google.protobuf.Empty) {} 13 | rpc SendUserAction(Action) returns (google.protobuf.Empty) {} 14 | } 15 | 16 | message UserIdentifier { 17 | int32 user_id = 1; 18 | } 19 | 20 | message User { 21 | int32 id = 1; 22 | string name = 2; 23 | string email = 3; 24 | string password = 4; 25 | } 26 | 27 | message Action { 28 | int32 user_id = 1; 29 | ActionEnum action = 2; 30 | bool success = 3; 31 | string error = 4; 32 | google.protobuf.Timestamp timestamp = 5; 33 | } 34 | 35 | enum ActionEnum { 36 | DEFAULT = 0; 37 | LOGIN = 1; 38 | LOGOUT = 2; 39 | PURCHASE = 3; 40 | RETURN = 4; 41 | ADD_TO_CART = 5; 42 | REMOVE_FROM_CART = 6; 43 | VIEW_ITEM = 7; 44 | VIEW_CART = 8; 45 | VIEW_PURCHASE_HISTORY = 9; 46 | } 47 | -------------------------------------------------------------------------------- /ex-3-streaming/solution/data-streamer/database/sqlite.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "context" 5 | "database/sql" 6 | "fmt" 7 | 8 | _ "github.com/mattn/go-sqlite3" 9 | ) 10 | 11 | type User struct { 12 | ID int 13 | Name string 14 | Email string 15 | Password string 16 | } 17 | 18 | type Client struct { 19 | db *sql.DB 20 | } 21 | 22 | func Setup() (*Client, error) { 23 | fileName := "database/ex-1-connection/sqlite.db" 24 | db, err := sql.Open("sqlite3", fileName) 25 | if err != nil { 26 | return nil, fmt.Errorf("error opening database: %v", err) 27 | } 28 | if err = db.Ping(); err != nil { 29 | return nil, fmt.Errorf("error pinging database: %v", err) 30 | } 31 | return &Client{db: db}, nil 32 | } 33 | 34 | func (c *Client) Close() error { 35 | return c.db.Close() 36 | } 37 | 38 | // GetUser gets a user from the database by ID. 39 | func (c *Client) GetUser(ctx context.Context, id int) (User, error) { 40 | var user User 41 | err := c.db.QueryRow("SELECT * FROM users WHERE id = $", id).Scan(&user.ID, &user.Name, &user.Email, &user.Password) 42 | if err != nil { 43 | return User{}, fmt.Errorf("error getting user: %v", err) 44 | } 45 | return user, nil 46 | } 47 | -------------------------------------------------------------------------------- /ex-3-streaming/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | "runtime" 9 | "time" 10 | 11 | "github.com/nats-io/nats.go" 12 | ) 13 | 14 | type Message struct { 15 | ID int 16 | Type string 17 | Body UserAction 18 | Timestamp time.Time 19 | } 20 | 21 | // action types: login, logout, purchase, return, add to cart, remove from cart, view item, view cart, view purchase history 22 | type UserAction struct { 23 | UserID int 24 | Action string 25 | Succeded bool 26 | Error string 27 | Timestamp time.Time 28 | } 29 | 30 | func main() { 31 | 32 | // setup NATS 33 | fmt.Println("Connecting to NATS...") 34 | nc, err := nats.Connect("demo.nats.io") 35 | if err != nil { 36 | panic(err) 37 | } 38 | time.Sleep(10 * time.Second) 39 | 40 | nc.Subscribe("hello.world", handleMessage) 41 | nc.Flush() 42 | 43 | if err := nc.LastError(); err != nil { 44 | log.Fatal(err) 45 | } 46 | 47 | go http.ListenAndServe(":8080", nil) 48 | 49 | runtime.Goexit() 50 | } 51 | 52 | func handleMessage(m *nats.Msg) { 53 | 54 | var msg Message 55 | err := json.Unmarshal(m.Data, &msg) 56 | if err != nil { 57 | log.Println(err) 58 | return 59 | } 60 | // TODO: aggregate data here and collect stats 61 | } 62 | -------------------------------------------------------------------------------- /database-demo/migrations/0001_game_create.sql: -------------------------------------------------------------------------------- 1 | -- +goose Up 2 | CREATE TABLE IF NOT EXISTS users ( 3 | id SERIAL PRIMARY KEY, 4 | username VARCHAR(255) UNIQUE NOT NULL, 5 | created_at TIMESTAMP NOT NULL DEFAULT NOW() 6 | ); 7 | 8 | CREATE TABLE IF NOT EXISTS questions ( 9 | id SERIAL PRIMARY KEY, 10 | question VARCHAR(255) NOT NULL, 11 | user_id INTEGER NOT NULL references users(id), 12 | game_id INTEGER NOT NULL references games(id) 13 | ); 14 | 15 | CREATE TABLE IF NOT EXISTS guesses ( 16 | id SERIAL PRIMARY KEY, 17 | guess VARCHAR(255) NOT NULL, 18 | user_id INTEGER NOT NULL references users(id), 19 | game_id INTEGER NOT NULL references games(id), 20 | correct BOOLEAN DEFAULT FALSE 21 | ); 22 | 23 | CREATE TABLE IF NOT EXISTS games ( 24 | id SERIAL PRIMARY KEY, 25 | host VARCHAR(255) NOT NULL, 26 | players VARCHAR(255)[5] NOT NULL references users(id), 27 | answer VARCHAR(255) NOT NULL, 28 | questions VARCHAR(255)[] references questions(id) , 29 | guesses VARCHAR(255)[] references guesses(id), 30 | start_time TIMESTAMP NOT NULL DEFAULT NOW(), 31 | end_time TIMESTAMP, 32 | ended BOOLEAN DEFAULT FALSE 33 | ); 34 | 35 | -- +goose Down 36 | 37 | DROP TABLE IF EXISTS users; 38 | DROP TABLE IF EXISTS questions; 39 | DROP TABLE IF EXISTS guesses; 40 | DROP TABLE IF EXISTS games; 41 | 42 | -------------------------------------------------------------------------------- /grpc-gateway-demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "fmt" 7 | "log" 8 | "os" 9 | "os/signal" 10 | "time" 11 | 12 | server "github.com/soypete/Golang_datatools_exercises/grpc-gateway-demo/server" 13 | ) 14 | 15 | var ( 16 | httpPort string 17 | grpcPort string 18 | ) 19 | 20 | func main() { 21 | flag.StringVar(&httpPort, "httpPort", ":8090", "HTTP Port to listen on") 22 | flag.StringVar(&grpcPort, "grpcPort", ":9090", "gRPC Port to listen on") 23 | flag.Parse() 24 | 25 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 26 | defer cancel() 27 | grpcServer := server.SetupGrpc() 28 | 29 | fmt.Println("gRPCServer is configured and listening on port :9090") 30 | 31 | go grpcServer.RunGrpc(ctx, grpcPort) 32 | 33 | // Configure Gateway Server 34 | grpcServer.SetupGateway(ctx, httpPort, grpcPort) 35 | fmt.Println("GatewayServer is configured and running on port :8090") 36 | err := grpcServer.GWServer.ListenAndServe() 37 | if err != nil { 38 | log.Fatalln(err) 39 | } 40 | // system close call to close all connections 41 | c := make(chan os.Signal, 1) 42 | signal.Notify(c, os.Interrupt) 43 | 44 | go func() { 45 | sig := <-c 46 | fmt.Printf("Got %s signal. Aborting...\n", sig) 47 | grpcServer.Close(ctx) 48 | os.Exit(1) 49 | }() 50 | 51 | } 52 | -------------------------------------------------------------------------------- /database-demo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "database/sql" 6 | "embed" 7 | "fmt" 8 | "net/url" 9 | 10 | "github.com/pressly/goose/v3" 11 | "github.com/soypete/WebServices-in-3-weeks/database/demo/database" 12 | ) 13 | 14 | //go:embed migrations/*.sql 15 | var embedMigrations embed.FS 16 | 17 | func main() { 18 | params := url.Values{} 19 | params.Set("sslmode", "disable") 20 | 21 | // this is a personal preference to use url.URL to 22 | // build up the connection string. This works well for 23 | // postgres, but other drivers might have their own quirks. 24 | connectionString := url.URL{ 25 | Scheme: "postgresql", 26 | User: url.UserPassword("postgres", "postgres"), 27 | Host: "localhost:5431", 28 | Path: "postgres", 29 | RawQuery: params.Encode(), 30 | } 31 | 32 | db, err := sql.Open("postgres", connectionString.String()) 33 | if err != nil { 34 | panic(err) 35 | } 36 | 37 | goose.SetBaseFS(embedMigrations) 38 | 39 | if err := goose.SetDialect("postgres"); err != nil { 40 | panic(err) 41 | } 42 | 43 | if err := goose.Up(db, "migrations"); err != nil { 44 | panic(err) 45 | } 46 | 47 | queires := database.New(db) 48 | 49 | user, err := queires.GetUser(context.Background(), "pete") 50 | if err != nil { 51 | panic(err) 52 | } 53 | fmt.Println(user) 54 | } 55 | -------------------------------------------------------------------------------- /ex-1-connection/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 1 2 | 3 | The first step of using a datastore is connecting it to your software program. In this exercise we will be using generic go program and creating a database connection to it. 4 | Using a sqLite database driver and this [main.go](/ex-1-connection/main.go) add a connection to the database of your choosing. After you have connected and verified your connection, explore the database. Make sure to query the database's users table and handle the error. Try running `SELECT`, `INSERT`, and `UPDATE` statements 5 | 6 | Follow up questions: 7 | *what kind of package organization would make sense for organizing your database logic? 8 | *what data base driver did you pick? 9 | \*did the data persist? 10 | 11 | _NOTE:_ You are free to use any db driver. You can run many datbases locally using docker. Below is an example of running postgres locally in a docker container. 12 | 13 | ``` 14 | docker pull postgres 15 | docker run -e POSTGRES_PASSWORD=my_password -e POSTGRES_USERNAME=user1 -p 5431:5432 postgres 16 | After you get docker running in your local environment setup your database. You will need to CREATE your tables and INSERT data into the table. You can do this in your Go app or via a sql script editor. psql is postgres's command line tool. 17 | ``` 18 | 19 | Solution [here](/databases/ex-1-connection/solution.go) 20 | -------------------------------------------------------------------------------- /ex-4-data-contracts/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 4: Using gRPC to validate data contract 2 | 3 | In this exercise we will be creating and validating Data contracts. We will be using the [protobuf](https://protobuf.dev/) + [grpc](https://grpc.io/) infrastructure to add a first layer of validation. This is a great way to restrict all payloads into a predictable and structured format. 4 | 5 | _Note_: This can also be accomplished using [JSON schema](https://json-schema.org/). gRPC is more popular amoung go developers, but there is no conceptual advatange in using `gRPC` over `JSON schema`. 6 | 7 | We are using the same data structures as in the previous streaming examples: 8 | 9 | ``` 10 | type Message struct { 11 | ID int 12 | Type string 13 | Body UserAction 14 | Timestamp time.Time 15 | } 16 | 17 | // action types: login, logout, purchase, return, add to cart, remove from cart, view item, view cart, view purchase history 18 | type UserAction struct { 19 | UserID int 20 | Action string 21 | Succeded bool 22 | Error string 23 | Timestamp time.Time 24 | } 25 | ``` 26 | 27 | To complete this exercise, add the required logic to the functions found in [solution.go](/server.go) to make the test pass. The tests are already implemented in [server_test.go](/server_test.go). The tests will start as all failing. You can check your test output by running 28 | 29 | ``` 30 | $ go test /ex-4-data-contracts -v 31 | ``` 32 | 33 | [Solution](/solution/server.go) 34 | 35 | Follow-up Questions: 36 | 37 | * What fields are required according to our current data contract? 38 | * Should any additional fields be required? 39 | -------------------------------------------------------------------------------- /ex-3-streaming/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 3 2 | 3 | In this exercise you will be agregating live event to count the number or user actions that occur. You are provided a database to reference and answer the follow-up question. 4 | 5 | Using provided [nats subscriber]() subscriber handle messages that come in. Handle the messages by parsing them into a struct. Using the data in the struct, collect stats about the total number of actions that take place for each action type. Below are a set of questions. Use the parsed data to answer the questions. Run your consumer program for 90 seconds to collect the stats and them print the answers to standard out. 6 | 7 | ``` 8 | type Message struct { 9 | ID int 10 | Type string 11 | Body UserAction 12 | Timestamp time.Time 13 | } 14 | ``` 15 | 16 | The following action types will be used. 17 | 18 | * login 19 | * logout 20 | * purchase 21 | * return 22 | * add to cart 23 | * remove from cart 24 | * view item 25 | * view cart, 26 | * view purchase history 27 | 28 | Print the answers to the following questions to your standard out. 29 | 30 | 1. How many purchases did `user 4` make? 31 | 2. how many "add item to cart" messages failed? 32 | 3. Of the total message processed how many were of `return` type? 33 | 34 | Solution [here](solution/main.go) 35 | 36 | _Note_: if you are following this on your own use docker to create a local nats server. That can be done with the following command: 37 | 38 | ``` 39 | docker run --name nats -p 4222:4222 -p 8222:8222 nats --http_port 8222 40 | ``` 41 | 42 | Make sure to change your connection to the following IP 43 | 44 | ``` 45 | nc, err := nats.Connect("http://localhost:4222") 46 | if err != nil { 47 | panic(err) 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /grpc-gateway-demo/proto/user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package user; 3 | 4 | import "google/api/annotations.proto"; 5 | import "google/protobuf/empty.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | import "protoc-gen-openapiv2/options/annotations.proto"; 8 | 9 | option go_package = "github.com/Soypete/Golang_datatools_exercises/ex-4-data-contracts/proto/gen/go"; 10 | 11 | service UserAction { 12 | rpc UpdateUser(User) returns (google.protobuf.Empty) { 13 | option (google.api.http) = { 14 | post: "/user/update/{id}" 15 | body: "*" 16 | }; 17 | } 18 | rpc GetUserInfo(UserIdentifier) returns (User) { 19 | option (google.api.http) = {get: "/user/getinfo/{user_id}"}; 20 | } 21 | rpc DeleteUser(UserIdentifier) returns (google.protobuf.Empty) { 22 | option (google.api.http) = { 23 | post: "/user/delete/{user_id}" 24 | body: "*" 25 | }; 26 | } 27 | rpc SendUserAction(Action) returns (google.protobuf.Empty) { 28 | option (google.api.http) = { 29 | post: "/action/send/{user_id}" 30 | body: "*" 31 | }; 32 | } 33 | } 34 | 35 | message UserIdentifier { 36 | int32 user_id = 1; 37 | } 38 | 39 | message User { 40 | int32 id = 1; 41 | string name = 2; 42 | string email = 3; 43 | string password = 4; 44 | } 45 | 46 | message Action { 47 | int32 user_id = 1; 48 | ActionEnum action = 2; 49 | bool success = 3; 50 | string error = 4; 51 | google.protobuf.Timestamp timestamp = 5; 52 | } 53 | 54 | enum ActionEnum { 55 | DEFAULT = 0; 56 | LOGIN = 1; 57 | LOGOUT = 2; 58 | PURCHASE = 3; 59 | RETURN = 4; 60 | ADD_TO_CART = 5; 61 | REMOVE_FROM_CART = 6; 62 | VIEW_ITEM = 7; 63 | VIEW_CART = 8; 64 | VIEW_PURCHASE_HISTORY = 9; 65 | } 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Golang_datatools_exercises 2 | 3 | exercises, activities, and questions for integrating data tools to your go program 4 | 5 | ## [![wakatime](https://wakatime.com/badge/user/953eeb5a-d347-44af-9d8b-a5b8a918cecf/project/815add1c-01f3-412e-b6cd-730805338e0e.svg)](https://wakatime.com/badge/user/953eeb5a-d347-44af-9d8b-a5b8a918cecf/project/815add1c-01f3-412e-b6cd-730805338e0e) 6 | 7 | ## Pre-requisites 8 | 9 | * [Go](https://go.dev/) installed and running 10 | * Working knowledge of go 11 | * git for cloning and using the repo 12 | 13 | ## New to go? 14 | 15 | If you are new to go, work through these exercises first 16 | 17 | * [Golang Zero to Hero](https://github.com/Soypete/Golang_tutorial_zero_to_hero) 18 | * [Tour of Go](https://go.dev/tour/welcome/1) 19 | * [Gophercises](https://gophercises.com/) 20 | 21 | --- 22 | 23 | ## Exercises 24 | 25 | * [Exercise 1](/ex-1-connection/README.md) - Connect a Data base to your Go Service 26 | * [Exercise 2](/ex-2-mocking-db-test/README.md) - Databases in tests 27 | * [Exercise 3](/ex-3-streaming/READEME.md) - connect a streaming client 28 | * [Exercise 4](/ex-4-data-contracts/README.md) - validate your data contract with grpc 29 | 30 | --- 31 | 32 | ## Live Demos 33 | 34 | ### DB Management 35 | 36 | Using tools to manage a database. Tools like goose and sqlc can be used to easliy abstract database management into your software stack. The following page is the resulting [code from the live demo](database-demo/main.go) 37 | 38 | [watch goose video](https://youtu.be/3TnEeRttvyo) 39 | [watch sqlc video](https://youtu.be/X5VGxx4aQAU) 40 | 41 | ### grpc-gateway 42 | 43 | Grpc is a valuable tool for managing data contracts. You can leverage grpc-gateway to still maintain restful best practices and accept json payloads while using protobufs to maintain structured data formats. You can view the demo code in [grpc-gateway-demo](/grpc-gateway-demo/main.go) 44 | 45 | --- 46 | 47 | ## Explore More 48 | 49 | * [pgx](https://github.com/jackc/pgx) 50 | * [pg](https://github.com/lib/pq) 51 | * [sqlx](https://github.com/jmoiron/sqlx) 52 | * [sqlc](https://sqlc.dev/) 53 | * [gRPC](https://grpc.io/) 54 | * [protobuf](https://protobuf.dev/) 55 | * [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway) 56 | -------------------------------------------------------------------------------- /ex-4-data-contracts/solution/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "strings" 7 | 8 | gengo "github.com/soypete/Golang_datatools_exercises/ex-4-data-contracts/gen/go/proto" 9 | "google.golang.org/protobuf/types/known/emptypb" 10 | ) 11 | 12 | type Server struct { 13 | gengo.UnimplementedUserActionServer 14 | } 15 | 16 | func setupServer() *Server { 17 | return &Server{} 18 | } 19 | 20 | func (s *Server) Close(ctx context.Context) error { 21 | ctx.Done() 22 | return nil 23 | } 24 | 25 | func (s *Server) UpdateUser(ctx context.Context, in *gengo.User) (*emptypb.Empty, error) { 26 | //validate required fields 27 | if in.Email == "" || in.Password == "" { 28 | return nil, errors.New("missing required fields") 29 | } 30 | //validate email 31 | if !strings.Contains(in.Email, "@") { 32 | return nil, errors.New("invalid email") 33 | } 34 | 35 | // NOTE: This is where we would call the database to update the user 36 | // Database index would start at 1 and is not required because we can use Sequential ID 37 | return &emptypb.Empty{}, nil 38 | } 39 | 40 | func (s *Server) GetUserInfo(ctx context.Context, in *gengo.UserIdentifier) (*gengo.User, error) { 41 | // validate required fields, ID default is 0. 0 is not a valid ID 42 | if in.UserId == 0 { 43 | return nil, errors.New("required ID fields") 44 | } 45 | 46 | // NOTE: This is where we would call the database to get the user 47 | // Database index would start at 1 48 | return &gengo.User{ 49 | Id: in.UserId, 50 | Name: "SoyPete", 51 | Email: "captainnobody1@email.com", 52 | }, nil 53 | } 54 | 55 | func (s *Server) DeleteUser(ctx context.Context, in *gengo.UserIdentifier) (*emptypb.Empty, error) { 56 | // validate required fields, ID default is 0. 0 is not a valid ID 57 | if in.UserId == 0 { 58 | return nil, errors.New("required ID fields") 59 | } 60 | return &emptypb.Empty{}, nil 61 | } 62 | 63 | func (s *Server) SendUserAction(ctx context.Context, in *gengo.Action) (*emptypb.Empty, error) { 64 | // validate required fields. 0 Is the Enum default value 65 | if in.Action == 0 { 66 | return nil, errors.New("required Action fields") 67 | } 68 | 69 | // ID default is 0. 0 is not a valid ID 70 | if in.UserId == 0 { 71 | return nil, errors.New("required UserId fields") 72 | } 73 | 74 | // NOTE: This is where we would call the database to get the user 75 | 76 | return &emptypb.Empty{}, nil 77 | } 78 | -------------------------------------------------------------------------------- /ex-2-mocking-db-tests/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | type Connector interface { 9 | selectUser(email string) (User, error) 10 | updateUser(user User) error 11 | deleteUser(email string) error 12 | } 13 | 14 | type Connection struct { 15 | db Connector 16 | } 17 | 18 | type User struct { 19 | ID int 20 | Name string 21 | Email string 22 | Password string 23 | } 24 | 25 | // endpoint: /getUser/{email} 26 | func (c *Connection) getUser(w http.ResponseWriter, r *http.Request) { 27 | email := r.URL.Path[len("/getUser/"):] 28 | // check if email is empty -> return 400 29 | if email == "" { 30 | http.Error(w, http.StatusText(400)+", email parameter cannot be empty", 400) 31 | return 32 | } 33 | user, err := c.db.selectUser(email) 34 | if err != nil { 35 | http.Error(w, http.StatusText(500)+", error while selecting user", 500) 36 | return 37 | } 38 | // return email and 200 39 | w.WriteHeader(200) 40 | err = json.NewEncoder(w).Encode(user) 41 | if err != nil { 42 | http.Error(w, http.StatusText(500)+", error while encoding user", 500) 43 | return 44 | } 45 | } 46 | 47 | // endpoint: /updateUser/{email} 48 | func (c *Connection) updateUser(w http.ResponseWriter, r *http.Request) { 49 | email := r.URL.Path[len("/updateUser/"):] 50 | // check if email is empty -> return 400 51 | if email == "" { 52 | http.Error(w, http.StatusText(400)+", email parameter cannot be empty", 400) 53 | return 54 | } 55 | defer r.Body.Close() 56 | var user User 57 | err := json.NewDecoder(r.Body).Decode(&user) 58 | if err != nil { 59 | http.Error(w, http.StatusText(500)+", error while decoding user", 500) 60 | return 61 | } 62 | 63 | err = c.db.updateUser(user) 64 | if err != nil { 65 | http.Error(w, http.StatusText(500)+", error while updating user", 500) 66 | return 67 | } 68 | 69 | // return response and 200 70 | w.WriteHeader(200) 71 | w.Write([]byte("user registered")) 72 | } 73 | 74 | // endpoint: /deleteUser/{email} 75 | func (c *Connection) deleteUser(w http.ResponseWriter, r *http.Request) { 76 | email := r.URL.Path[len("/deleteUser/"):] 77 | // check if email is empty -> return 400 78 | if email == "" { 79 | http.Error(w, http.StatusText(400)+", email parameter cannot be empty", 400) 80 | return 81 | } 82 | 83 | err := c.db.deleteUser(email) 84 | if err != nil { 85 | http.Error(w, http.StatusText(500)+", error while deleting user", 500) 86 | return 87 | } 88 | // return response and 200 89 | w.WriteHeader(200) 90 | w.Write([]byte("user deleted")) // TODO: return deleted email 91 | } 92 | -------------------------------------------------------------------------------- /ex-2-mocking-db-tests/solution/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | type Connector interface { 9 | selectUser(email string) (User, error) 10 | updateUser(user User) error 11 | deleteUser(email string) error 12 | } 13 | 14 | type Connection struct { 15 | db Connector 16 | } 17 | 18 | type User struct { 19 | ID int 20 | Name string 21 | Email string 22 | Password string 23 | } 24 | 25 | // endpoint: /getUser/{email} 26 | func (c *Connection) getUser(w http.ResponseWriter, r *http.Request) { 27 | email := r.URL.Path[len("/getUser/"):] 28 | // check if email is empty -> return 400 29 | if email == "" { 30 | http.Error(w, http.StatusText(400)+", email parameter cannot be empty", 400) 31 | return 32 | } 33 | user, err := c.db.selectUser(email) 34 | if err != nil { 35 | http.Error(w, http.StatusText(500)+", error while selecting user", 500) 36 | return 37 | } 38 | // return email and 200 39 | w.WriteHeader(200) 40 | err = json.NewEncoder(w).Encode(user) 41 | if err != nil { 42 | http.Error(w, http.StatusText(500)+", error while encoding user", 500) 43 | return 44 | } 45 | } 46 | 47 | // endpoint: /updateUser/{email} 48 | func (c *Connection) updateUser(w http.ResponseWriter, r *http.Request) { 49 | email := r.URL.Path[len("/updateUser/"):] 50 | // check if email is empty -> return 400 51 | if email == "" { 52 | http.Error(w, http.StatusText(400)+", email parameter cannot be empty", 400) 53 | return 54 | } 55 | defer r.Body.Close() 56 | var user User 57 | err := json.NewDecoder(r.Body).Decode(&user) 58 | if err != nil { 59 | http.Error(w, http.StatusText(500)+", error while decoding user", 500) 60 | return 61 | } 62 | 63 | err = c.db.updateUser(user) 64 | if err != nil { 65 | http.Error(w, http.StatusText(500)+", error while updating user", 500) 66 | return 67 | } 68 | 69 | // return response and 200 70 | w.WriteHeader(200) 71 | w.Write([]byte("user registered")) 72 | } 73 | 74 | // endpoint: /deleteUser/{email} 75 | func (c *Connection) deleteUser(w http.ResponseWriter, r *http.Request) { 76 | email := r.URL.Path[len("/deleteUser/"):] 77 | // check if email is empty -> return 400 78 | if email == "" { 79 | http.Error(w, http.StatusText(400)+", email parameter cannot be empty", 400) 80 | return 81 | } 82 | 83 | err := c.db.deleteUser(email) 84 | if err != nil { 85 | http.Error(w, http.StatusText(500)+", error while deleting user", 500) 86 | return 87 | } 88 | // return response and 200 89 | w.WriteHeader(200) 90 | w.Write([]byte("user deleted")) // TODO: return deleted email 91 | } 92 | -------------------------------------------------------------------------------- /ex-2-mocking-db-tests/server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http/httptest" 7 | "testing" 8 | ) 9 | 10 | type dbPassMock struct{} 11 | type dbFailMock struct{} 12 | 13 | // TODO: Add more mock here 14 | 15 | func TestUserendpoints(t *testing.T) { 16 | t.Run("Get Username: Pass", testPassGetUsername) 17 | t.Run("Get Username: no Username", testFailGetUsername) 18 | t.Run("Update Username: Pass", testPassUpdateUser) 19 | t.Run("Update Username:Fail", testFailUpdateUsername) 20 | t.Run("Delete Username: Pass", testPassDeleteUser) 21 | t.Run("Delete Username:Fail", testFailDeleteUsername) 22 | } 23 | 24 | func testPassGetUsername(t *testing.T) { 25 | c := Connection{ 26 | db: &dbPassMock{}, 27 | } 28 | w := httptest.NewRecorder() 29 | req := httptest.NewRequest("GET", "/getUser/captainnobody1@email.com", nil) 30 | c.getUser(w, req) 31 | resp := w.Result() 32 | if resp.StatusCode != 200 { 33 | t.Fatalf("Expected status code 200, got %d", resp.StatusCode) 34 | } 35 | } 36 | 37 | func testFailGetUsername(t *testing.T) { 38 | c := Connection{ 39 | db: &dbFailMock{}, 40 | } 41 | w := httptest.NewRecorder() 42 | req := httptest.NewRequest("GET", "/getUser/captainnobody1@email.com", nil) 43 | c.getUser(w, req) 44 | resp := w.Result() 45 | if resp.StatusCode != 500 { 46 | t.Fatalf("Expected status code 500, got %d", resp.StatusCode) 47 | } 48 | } 49 | 50 | func testPassUpdateUser(t *testing.T) { 51 | c := Connection{ 52 | db: &dbPassMock{}, 53 | } 54 | w := httptest.NewRecorder() 55 | err := json.NewEncoder(w).Encode(User{ 56 | ID: 1, 57 | Name: "Miriah Peterson", 58 | Email: "captainnboody1@gmail.com", 59 | }) 60 | if err != nil { 61 | t.Fatalf("Error encoding JSON") 62 | } 63 | req := httptest.NewRequest("POST", "/updateUser/captainnobody1@email.com", nil) 64 | c.updateUser(w, req) 65 | resp := w.Result() 66 | if resp.StatusCode != 200 { 67 | fmt.Println(resp) 68 | t.Fatalf("Expected status code 200, got %d", resp.StatusCode) 69 | } 70 | } 71 | 72 | func testFailUpdateUsername(t *testing.T) { 73 | c := Connection{ 74 | db: &dbFailMock{}, 75 | } 76 | w := httptest.NewRecorder() 77 | req := httptest.NewRequest("POST", "/updateUser/captainnobody1@email.com", nil) 78 | c.updateUser(w, req) 79 | resp := w.Result() 80 | if resp.StatusCode != 500 { 81 | t.Fatalf("Expected status code 500, got %d", resp.StatusCode) 82 | } 83 | } 84 | 85 | func testPassDeleteUser(t *testing.T) { 86 | c := Connection{ 87 | db: &dbPassMock{}, 88 | } 89 | w := httptest.NewRecorder() 90 | req := httptest.NewRequest("GET", "/deleteUser/captainnobody1@gmail.com", nil) 91 | c.deleteUser(w, req) 92 | resp := w.Result() 93 | if resp.StatusCode != 200 { 94 | t.Fatalf("Expected status code 200, got %d", resp.StatusCode) 95 | } 96 | } 97 | 98 | func testFailDeleteUsername(t *testing.T) { 99 | c := Connection{ 100 | db: &dbFailMock{}, 101 | } 102 | w := httptest.NewRecorder() 103 | req := httptest.NewRequest("GET", "/deleteUser/captainnobody1@gmail.com", nil) 104 | c.deleteUser(w, req) 105 | resp := w.Result() 106 | if resp.StatusCode != 500 { 107 | t.Fatalf("Expected status code 500, got %d", resp.StatusCode) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /ex-3-streaming/solution/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "fmt" 7 | "log" 8 | "net/http" 9 | "runtime" 10 | "time" 11 | 12 | "expvar" 13 | 14 | "github.com/nats-io/nats.go" 15 | ) 16 | 17 | type Message struct { 18 | ID int 19 | Type string 20 | Body UserAction 21 | Timestamp time.Time 22 | } 23 | 24 | // action types: login, logout, purchase, return, add to cart, remove from cart, view item, view cart, view purchase history 25 | type UserAction struct { 26 | UserID int 27 | Action string 28 | Succeded bool 29 | Error string 30 | Timestamp time.Time 31 | } 32 | 33 | var ( 34 | countLogin expvar.Int 35 | countLogout expvar.Int 36 | countPurchase expvar.Int 37 | countReturn expvar.Int 38 | countAddToCart expvar.Int 39 | countRemoveFromCart expvar.Int 40 | countViewItem expvar.Int 41 | countViewCart expvar.Int 42 | countViewPurchaseHistory expvar.Int 43 | 44 | url string 45 | topic string 46 | ) 47 | 48 | func main() { 49 | flag.StringVar(&url, "url", nats.DefaultURL, "The nats server URLs (separated by comma)") 50 | flag.StringVar(&topic, "topic", "hello.world", "The nats topic") 51 | flag.Parse() 52 | 53 | // setup expvar server 54 | expvar.Publish("countLogin", &countLogin) 55 | expvar.Publish("countLogout", &countLogout) 56 | expvar.Publish("countPurchase", &countPurchase) 57 | expvar.Publish("countReturn", &countReturn) 58 | expvar.Publish("countAddToCart", &countAddToCart) 59 | expvar.Publish("countRemoveFromCart", &countRemoveFromCart) 60 | expvar.Publish("countViewItem", &countViewItem) 61 | expvar.Publish("countViewCart", &countViewCart) 62 | expvar.Publish("countViewPurchaseHistory", &countViewPurchaseHistory) 63 | 64 | // setup NATS 65 | fmt.Println("Connecting to NATS...") 66 | nc, err := nats.Connect(url) 67 | if err != nil { 68 | panic(err) 69 | } 70 | time.Sleep(10 * time.Second) 71 | 72 | nc.Subscribe(topic, handleMessage) 73 | nc.Flush() 74 | 75 | if err := nc.LastError(); err != nil { 76 | log.Fatal(err) 77 | } 78 | 79 | go http.ListenAndServe(":8080", nil) 80 | 81 | runtime.Goexit() 82 | } 83 | 84 | func handleMessage(m *nats.Msg) { 85 | 86 | var msg Message 87 | err := json.Unmarshal(m.Data, &msg) 88 | if err != nil { 89 | log.Println(err) 90 | return 91 | } 92 | switch msg.Body.Action { 93 | case "login": 94 | countLogin.Add(1) 95 | // handle login 96 | case "logout": 97 | countLogout.Add(1) 98 | // handle logout 99 | case "purchase": 100 | countPurchase.Add(1) 101 | // handle purchase 102 | case "return": 103 | countReturn.Add(1) 104 | // handle return 105 | case "add to cart": 106 | countAddToCart.Add(1) 107 | // handle add to cart 108 | case "remove from cart": 109 | countRemoveFromCart.Add(1) 110 | // handle remove from cart 111 | case "view item": 112 | countViewItem.Add(1) 113 | // handle view item 114 | case "view cart": 115 | countViewCart.Add(1) 116 | // handle view cart 117 | case "view purchase history": 118 | countViewPurchaseHistory.Add(1) 119 | // handle view purchase history 120 | default: 121 | fmt.Println("Unknown message type") 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /ex-3-streaming/solution/data-streamer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "fmt" 7 | "log" 8 | "math/rand" 9 | "os" 10 | "os/signal" 11 | "sync" 12 | "time" 13 | 14 | "github.com/nats-io/nats.go" 15 | ) 16 | 17 | type Message struct { 18 | ID int 19 | Type string 20 | Body UserAction 21 | Timestamp time.Time 22 | } 23 | 24 | // action types: login, logout, purchase, return, add to cart, remove from cart, view item, view cart, view purchase history 25 | type UserAction struct { 26 | UserID int 27 | Action string 28 | Succeded bool 29 | Error string 30 | Timestamp time.Time 31 | } 32 | 33 | var UserActions = []string{"login", "logout", "purchase", "return", "add to cart", "remove from cart", "view item", "view cart", "view purchase history"} 34 | 35 | // MessageCreate creates a message with a random ID, a type, a body, and a timestamp. 36 | // It returns the message as a serialized byte array and an error if there is one. 37 | func MessageCreate(messageType string, messageBody UserAction) ([]byte, error) { 38 | message := Message{ 39 | ID: rand.Intn(100000), 40 | Type: messageType, 41 | Body: messageBody, 42 | Timestamp: time.Now(), 43 | } 44 | return json.Marshal(message) 45 | } 46 | 47 | // chooseMessageType chooses a message type at random. 48 | func chooseMessageType() string { 49 | return UserActions[rand.Intn(len(UserActions))] 50 | } 51 | 52 | func (u *UserAction) getErrorMessage() { 53 | if u.Succeded { 54 | u.Error = "" 55 | } 56 | switch u.Action { 57 | case "login": 58 | u.Error = "login failed" 59 | case "logout": 60 | u.Error = "logout failed" 61 | case "purchase": 62 | u.Error = "purchase failed" 63 | case "return": 64 | u.Error = "return failed" 65 | case "add to cart": 66 | u.Error = "add to cart failed" 67 | case "remove from cart": 68 | u.Error = "remove from cart failed" 69 | case "view item": 70 | u.Error = "view item failed" 71 | case "view cart": 72 | u.Error = "view cart failed" 73 | case "view purchase history": 74 | u.Error = "view purchase history failed" 75 | default: 76 | u.Error = "unknown action" 77 | } 78 | } 79 | 80 | // messagePublish publishes a message to a NATS server. 81 | // It returns an error if there is one. 82 | func messagePublish(nc *nats.Conn) error { 83 | 84 | // populate message body 85 | userAction := UserAction{ 86 | UserID: rand.Intn(20), // there are 20 users in the database 87 | Action: chooseMessageType(), 88 | Succeded: rand.Intn(2) == 0, 89 | Timestamp: time.Now(), 90 | } 91 | userAction.getErrorMessage() 92 | 93 | // create message 94 | message, err := MessageCreate("userAction", userAction) 95 | if err != nil { 96 | return err 97 | } 98 | 99 | fmt.Println(string(topic)) 100 | // publish message 101 | nc.Publish(topic, message) 102 | log.Printf("Published message: %s\n", message) 103 | return nil 104 | } 105 | 106 | var ( 107 | url string 108 | topic string 109 | ) 110 | 111 | func main() { 112 | flag.StringVar(&url, "url", nats.DefaultURL, "The nats server URLs (separated by comma)") 113 | flag.StringVar(&topic, "topic", "hello.world", "The nats topic") 114 | flag.Parse() 115 | 116 | fmt.Println("url:", url) 117 | nc, err := nats.Connect(url) 118 | if err != nil { 119 | panic(err) 120 | } 121 | 122 | // symulate users on many devices 123 | wg := new(sync.WaitGroup) 124 | wg.Add(1) 125 | go func() { 126 | for { 127 | messagePublish(nc) 128 | time.Sleep(1 * time.Second) 129 | } 130 | }() 131 | wg.Wait() 132 | 133 | // system close call to close all connections 134 | c := make(chan os.Signal, 1) 135 | signal.Notify(c, os.Interrupt) 136 | 137 | go func() { 138 | sig := <-c 139 | fmt.Printf("Got %s signal. Aborting...\n", sig) 140 | wg.Done() 141 | nc.Close() 142 | os.Exit(1) 143 | }() 144 | } 145 | -------------------------------------------------------------------------------- /ex-2-mocking-db-tests/solution/server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http/httptest" 7 | "testing" 8 | ) 9 | 10 | type dbPassMock struct{} 11 | 12 | func (d *dbPassMock) selectUser(email string) (User, error) { 13 | return User{ 14 | ID: 1, 15 | Name: "Miriah Peterson", 16 | Email: "captainnobody1@email.com", 17 | }, nil 18 | } 19 | 20 | func (d *dbPassMock) updateUser(user User) error { 21 | return nil 22 | } 23 | 24 | func (d *dbPassMock) deleteUser(email string) error { 25 | return nil 26 | } 27 | 28 | type dbFailMock struct{} 29 | 30 | func (d *dbFailMock) selectUser(email string) (User, error) { 31 | return User{}, fmt.Errorf("Error") 32 | } 33 | 34 | func (d *dbFailMock) updateUser(user User) error { 35 | return fmt.Errorf("Error") 36 | } 37 | 38 | func (d *dbFailMock) deleteUser(email string) error { 39 | return fmt.Errorf("Error") 40 | } 41 | 42 | func TestUserendpoints(t *testing.T) { 43 | t.Run("Get Username: Pass", testPassGetUsername) 44 | t.Run("Get Username: no Username", testFailGetUsername) 45 | t.Run("Update Username: Pass", testPassUpdateUser) 46 | t.Run("Update Username:Fail", testFailUpdateUsername) 47 | t.Run("Delete Username: Pass", testPassDeleteUser) 48 | t.Run("Delete Username:Fail", testFailDeleteUsername) 49 | } 50 | 51 | func testPassGetUsername(t *testing.T) { 52 | c := Connection{ 53 | db: &dbPassMock{}, 54 | } 55 | w := httptest.NewRecorder() 56 | req := httptest.NewRequest("GET", "/getUser/captainnobody1@email.com", nil) 57 | c.getUser(w, req) 58 | resp := w.Result() 59 | if resp.StatusCode != 200 { 60 | t.Fatalf("Expected status code 200, got %d", resp.StatusCode) 61 | } 62 | } 63 | 64 | func testFailGetUsername(t *testing.T) { 65 | c := Connection{ 66 | db: &dbFailMock{}, 67 | } 68 | w := httptest.NewRecorder() 69 | req := httptest.NewRequest("GET", "/getUser/captainnobody1@email.com", nil) 70 | c.getUser(w, req) 71 | resp := w.Result() 72 | if resp.StatusCode != 500 { 73 | t.Fatalf("Expected status code 500, got %d", resp.StatusCode) 74 | } 75 | } 76 | 77 | func testPassUpdateUser(t *testing.T) { 78 | c := Connection{ 79 | db: &dbPassMock{}, 80 | } 81 | w := httptest.NewRecorder() 82 | err := json.NewEncoder(w).Encode(User{ 83 | ID: 1, 84 | Name: "Miriah Peterson", 85 | Email: "captainnboody1@gmail.com", 86 | }) 87 | if err != nil { 88 | t.Fatalf("Error encoding JSON") 89 | } 90 | req := httptest.NewRequest("POST", "/updateUser/captainnobody1@email.com", nil) 91 | c.updateUser(w, req) 92 | resp := w.Result() 93 | if resp.StatusCode != 200 { 94 | fmt.Println(resp) 95 | t.Fatalf("Expected status code 200, got %d", resp.StatusCode) 96 | } 97 | } 98 | 99 | func testFailUpdateUsername(t *testing.T) { 100 | c := Connection{ 101 | db: &dbFailMock{}, 102 | } 103 | w := httptest.NewRecorder() 104 | req := httptest.NewRequest("POST", "/updateUser/captainnobody1@email.com", nil) 105 | c.updateUser(w, req) 106 | resp := w.Result() 107 | if resp.StatusCode != 500 { 108 | t.Fatalf("Expected status code 500, got %d", resp.StatusCode) 109 | } 110 | } 111 | 112 | func testPassDeleteUser(t *testing.T) { 113 | c := Connection{ 114 | db: &dbPassMock{}, 115 | } 116 | w := httptest.NewRecorder() 117 | req := httptest.NewRequest("GET", "/deleteUser/captainnobody1@gmail.com", nil) 118 | c.deleteUser(w, req) 119 | resp := w.Result() 120 | if resp.StatusCode != 200 { 121 | t.Fatalf("Expected status code 200, got %d", resp.StatusCode) 122 | } 123 | } 124 | 125 | func testFailDeleteUsername(t *testing.T) { 126 | c := Connection{ 127 | db: &dbFailMock{}, 128 | } 129 | w := httptest.NewRecorder() 130 | req := httptest.NewRequest("GET", "/deleteUser/captainnobody1@gmail.com", nil) 131 | c.deleteUser(w, req) 132 | resp := w.Result() 133 | if resp.StatusCode != 500 { 134 | t.Fatalf("Expected status code 500, got %d", resp.StatusCode) 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /grpc-gateway-demo/server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "net" 8 | "net/http" 9 | "strings" 10 | 11 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 12 | gen "github.com/soypete/Golang_datatools_exercises/grpc-gateway-demo/gen/proto" 13 | "google.golang.org/grpc" 14 | "google.golang.org/grpc/credentials/insecure" 15 | "google.golang.org/protobuf/types/known/emptypb" 16 | ) 17 | 18 | type Server struct { 19 | gen.UnimplementedUserActionServer 20 | GWServer *http.Server 21 | } 22 | 23 | func SetupGrpc() *Server { 24 | return &Server{} 25 | } 26 | 27 | // SetupGateway creates the Rest server via grpc connection/ 28 | func (s *Server) SetupGateway(ctx context.Context, port string, grpcPort string) error { 29 | conn, err := grpc.DialContext( 30 | ctx, 31 | "localhost"+grpcPort, 32 | grpc.WithBlock(), 33 | grpc.WithTransportCredentials(insecure.NewCredentials()), 34 | ) 35 | 36 | if err != nil { 37 | return fmt.Errorf("failed to setup grpc client connection: %w", err) 38 | } 39 | 40 | gwmux := runtime.NewServeMux() 41 | // Register Greeter 42 | if err = gen.RegisterUserActionHandler(ctx, gwmux, conn); err != nil { 43 | return fmt.Errorf("failed to register gateway: %w", err) 44 | } 45 | 46 | s.GWServer = &http.Server{ 47 | Addr: "localhost" + port, 48 | Handler: gwmux, 49 | } 50 | 51 | return nil 52 | } 53 | 54 | // startup and run grpc server 55 | func (s *Server) RunGrpc(ctx context.Context, port string) error { 56 | lis, err := net.Listen("tcp", "localhost"+port) 57 | if err != nil { 58 | return fmt.Errorf("cannot setup tcp connection: %w", err) 59 | } 60 | 61 | grpcServer := grpc.NewServer() 62 | gen.RegisterUserActionServer(grpcServer, s) 63 | 64 | err = grpcServer.Serve(lis) 65 | if err != nil { 66 | return fmt.Errorf("grpc server failure: %w", err) 67 | } 68 | return nil 69 | } 70 | 71 | // startup and run grpc-gateway server 72 | func (s *Server) Close(ctx context.Context) error { 73 | ctx.Done() 74 | return nil 75 | } 76 | 77 | // UpdateUser updates a user 78 | // curl localhost:8090/user -X -d '{"id": 1, "name": "SoyPete", "email": "captainnobody1@gmail", "password": "password"}' 79 | func (s *Server) UpdateUser(ctx context.Context, in *gen.User) (*emptypb.Empty, error) { 80 | //validate required fields 81 | if in.Email == "" || in.Password == "" { 82 | return nil, errors.New("missing required fields") 83 | } 84 | //validate email 85 | if !strings.Contains(in.Email, "@") { 86 | return nil, errors.New("invalid email") 87 | } 88 | 89 | // NOTE: This is where we would call the database to update the user 90 | // Database index would start at 1 and is not required because we can use Sequential ID 91 | return &emptypb.Empty{}, nil 92 | } 93 | 94 | // GetUserInfo gets a user 95 | // curl localhost:8090/user/getinfo/1 96 | func (s *Server) GetUserInfo(ctx context.Context, in *gen.UserIdentifier) (*gen.User, error) { 97 | // validate required fields, ID default is 0. 0 is not a valid ID 98 | if in.UserId == 0 { 99 | return nil, errors.New("required ID fields") 100 | } 101 | 102 | // NOTE: This is where we would call the database to get the user 103 | // Database index would start at 1 104 | return &gen.User{ 105 | Id: in.UserId, 106 | Name: "SoyPete", 107 | Email: "captainnobody1@email.com", 108 | }, nil 109 | } 110 | 111 | // DeleteUser deletes a user 112 | // curl localhost:8090/user/delete/1 -X DELETE 113 | func (s *Server) DeleteUser(ctx context.Context, in *gen.UserIdentifier) (*emptypb.Empty, error) { 114 | // validate required fields, ID default is 0. 0 is not a valid ID 115 | if in.UserId == 0 { 116 | return nil, errors.New("required ID fields") 117 | } 118 | return &emptypb.Empty{}, nil 119 | } 120 | 121 | // SendUserAction sends a user action 122 | // curl localhost:8090/user/action -X -d '{"action": 1, "userId": 1}' 123 | func (s *Server) SendUserAction(ctx context.Context, in *gen.Action) (*emptypb.Empty, error) { 124 | // validate required fields. 0 Is the Enum default value 125 | if in.Action == 0 { 126 | return nil, errors.New("required Action fields") 127 | } 128 | 129 | // ID default is 0. 0 is not a valid ID 130 | if in.UserId == 0 { 131 | return nil, errors.New("required UserId fields") 132 | } 133 | 134 | // NOTE: This is where we would call the database to get the user 135 | 136 | return &emptypb.Empty{}, nil 137 | } 138 | -------------------------------------------------------------------------------- /ex-1-connection/solution/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | 8 | _ "github.com/mattn/go-sqlite3" 9 | ) 10 | 11 | func main() { 12 | fileName := "ex-1-connection/sqlite.db" 13 | db, err := sql.Open("sqlite3", fileName) 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | if err = db.Ping(); err != nil { 18 | log.Fatal(err) 19 | } 20 | fmt.Println("Connected!") 21 | 22 | _, err = db.Exec("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT UNIQUE, password TEXT NOT NULL)") 23 | if err != nil { 24 | log.Fatal(err) 25 | } 26 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('John Doe', ' john.doe@email.com', 'opensesame')") 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Jane Smith', 'smithjane@email.com', 'opensesame')") 31 | if err != nil { 32 | log.Fatal(err) 33 | } 34 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Robert Johnson', 'me@robertjohnson.com', 'opensesame')") 35 | if err != nil { 36 | log.Fatal(err) 37 | } 38 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Emily Davis', 'emily_davis@email.com', 'opensesame')") 39 | if err != nil { 40 | log.Fatal(err) 41 | } 42 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Michael Wilson', 'mwilson@email.com', 'opensesame')") 43 | if err != nil { 44 | log.Fatal(err) 45 | } 46 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Sarah Brown', 'sbbrown@email.com', 'opensesame')") 47 | if err != nil { 48 | log.Fatal(err) 49 | } 50 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('William Jones', 'whjones@email.com', 'opensesame')") 51 | if err != nil { 52 | log.Fatal(err) 53 | } 54 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Olivia Taylor', 'olivia.taylord@email.com', 'opensesame')") 55 | if err != nil { 56 | log.Fatal(err) 57 | } 58 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('David Evans', 'david@evans.com', 'opensesame')") 59 | if err != nil { 60 | log.Fatal(err) 61 | } 62 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Sophia Miller', 'sophiamiller@sophiamiller.com', 'opensesame')") 63 | if err != nil { 64 | log.Fatal(err) 65 | } 66 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('James Wilson', 'jamesthewil@email.com', 'opensesame')") 67 | if err != nil { 68 | log.Fatal(err) 69 | } 70 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Ava Martin', 'avamart@email.com', 'opensesame')") 71 | if err != nil { 72 | log.Fatal(err) 73 | } 74 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Charles Anderson', 'charles@anderson', 'opensesame')") 75 | if err != nil { 76 | log.Fatal(err) 77 | } 78 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Mia Martinez', 'miacasaessucasa@martinez.com', 'opensesame')") 79 | if err != nil { 80 | log.Fatal(err) 81 | } 82 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Joseph Thomas', 'joe@thomas.com', 'opensesame')") 83 | if err != nil { 84 | log.Fatal(err) 85 | } 86 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Chloe White', 'chloewhite@email.com', 'opensesame')") 87 | if err != nil { 88 | log.Fatal(err) 89 | } 90 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Daniel Harris', 'test@user.com', 'opensesame')") 91 | if err != nil { 92 | log.Fatal(err) 93 | } 94 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Emma Moore', 'emma_more@test.com', 'opensesame')") 95 | if err != nil { 96 | log.Fatal(err) 97 | } 98 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Matthew Clark', 'matt_clark@email.com', 'opensesame')") 99 | if err != nil { 100 | log.Fatal(err) 101 | } 102 | _, err = db.Exec("INSERT INTO users (name, email, password) VALUES ('Harper Lewis', 'harp@lewis.com', 'opensesame')") 103 | if err != nil { 104 | log.Fatal(err) 105 | } 106 | 107 | rows, err := db.Query("SELECT * FROM users") 108 | if err != nil { 109 | log.Fatal(err) 110 | } 111 | defer rows.Close() 112 | for rows.Next() { 113 | var id int 114 | var name string 115 | var email string 116 | var password string 117 | rows.Scan(&id, &name, &email, &password) 118 | fmt.Println(id, name, email, password) 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /grpc-gateway-demo/server/server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "reflect" 6 | "testing" 7 | "time" 8 | 9 | gengo "github.com/soypete/Golang_datatools_exercises/ex-4-data-contracts/gen/go/proto" 10 | "google.golang.org/protobuf/types/known/emptypb" 11 | "google.golang.org/protobuf/types/known/timestamppb" 12 | ) 13 | 14 | func TestServer_UpdateUser(t *testing.T) { 15 | tests := []struct { 16 | name string 17 | ctx context.Context 18 | in *gengo.User 19 | want *emptypb.Empty 20 | wantErr bool 21 | }{ 22 | { 23 | name: "Update User:Success", 24 | ctx: context.Background(), 25 | in: &gengo.User{ 26 | Id: 1, 27 | Name: "SoyPete", 28 | Password: "password", 29 | Email: "captainnobody1@gmail.com", 30 | }, 31 | want: &emptypb.Empty{}, 32 | wantErr: false, 33 | }, 34 | { 35 | name: "Update User:Fail - Invalid Email", 36 | ctx: context.Background(), 37 | in: &gengo.User{ 38 | Id: 1, 39 | Name: "SoyPete", 40 | Email: "captainnobody1", 41 | Password: "password", 42 | }, 43 | want: nil, 44 | wantErr: true, 45 | }, 46 | { 47 | name: "Update User:Fail - No Password", 48 | ctx: context.Background(), 49 | in: &gengo.User{ 50 | Id: 1, 51 | Name: "SoyPete", 52 | Email: "captainnobody1@email.com", 53 | }, 54 | want: nil, 55 | wantErr: true, 56 | }, 57 | { 58 | name: "Update User:Fail - No Email", 59 | ctx: context.Background(), 60 | in: &gengo.User{ 61 | Id: 1, 62 | Name: "SoyPete", 63 | Password: "password", 64 | }, 65 | want: nil, 66 | wantErr: true, 67 | }, 68 | } 69 | for _, tt := range tests { 70 | t.Run(tt.name, func(t *testing.T) { 71 | s := setupGrpc() 72 | got, err := s.UpdateUser(tt.ctx, tt.in) 73 | if (err != nil) != tt.wantErr { 74 | t.Errorf("Server.UpdateUser() error = %v, wantErr %v", err, tt.wantErr) 75 | return 76 | } 77 | if !reflect.DeepEqual(got, tt.want) { 78 | t.Errorf("Server.UpdateUser() = %v, want %v", got, tt.want) 79 | } 80 | }) 81 | } 82 | } 83 | 84 | func TestServer_GetUserInfo(t *testing.T) { 85 | tests := []struct { 86 | name string 87 | ctx context.Context 88 | in *gengo.UserIdentifier 89 | want *gengo.User 90 | wantErr bool 91 | }{ 92 | { 93 | name: "Get User:Success", 94 | ctx: context.Background(), 95 | in: &gengo.UserIdentifier{ 96 | UserId: 1, 97 | }, 98 | want: &gengo.User{ 99 | Id: 1, 100 | Name: "SoyPete", 101 | Email: "captainnobody1@email.com", 102 | // Do not want to return password 103 | }, 104 | wantErr: false, 105 | }, 106 | { 107 | name: "Get User:Fail - Invalid ID", 108 | ctx: context.Background(), 109 | in: &gengo.UserIdentifier{}, 110 | want: nil, 111 | wantErr: true, 112 | }, 113 | } 114 | for _, tt := range tests { 115 | t.Run(tt.name, func(t *testing.T) { 116 | s := setupGrpc() 117 | got, err := s.GetUserInfo(tt.ctx, tt.in) 118 | if (err != nil) != tt.wantErr { 119 | t.Errorf("Server.GetUserInfo() error = %v, wantErr %v", err, tt.wantErr) 120 | return 121 | } 122 | if !reflect.DeepEqual(got, tt.want) { 123 | t.Errorf("Server.GetUserInfo() = %v, want %v", got, tt.want) 124 | } 125 | }) 126 | } 127 | } 128 | 129 | func TestServer_DeleteUser(t *testing.T) { 130 | tests := []struct { 131 | name string 132 | ctx context.Context 133 | in *gengo.UserIdentifier 134 | want *emptypb.Empty 135 | wantErr bool 136 | }{ 137 | { 138 | name: "Delete User:Success", 139 | ctx: context.Background(), 140 | in: &gengo.UserIdentifier{ 141 | UserId: 1, 142 | }, 143 | want: &emptypb.Empty{}, 144 | wantErr: false, 145 | }, 146 | { 147 | name: "Delete User:Fail - Invalid ID", 148 | ctx: context.Background(), 149 | in: &gengo.UserIdentifier{}, 150 | want: nil, 151 | wantErr: true, 152 | }, 153 | } 154 | for _, tt := range tests { 155 | t.Run(tt.name, func(t *testing.T) { 156 | s := setupGrpc() 157 | got, err := s.DeleteUser(tt.ctx, tt.in) 158 | if (err != nil) != tt.wantErr { 159 | t.Errorf("Server.DeleteUser() error = %v, wantErr %v", err, tt.wantErr) 160 | return 161 | } 162 | if !reflect.DeepEqual(got, tt.want) { 163 | t.Errorf("Server.DeleteUser() = %v, want %v", got, tt.want) 164 | } 165 | }) 166 | } 167 | } 168 | 169 | func TestServer_SendUserAction(t *testing.T) { 170 | tests := []struct { 171 | name string 172 | ctx context.Context 173 | in *gengo.Action 174 | want *emptypb.Empty 175 | wantErr bool 176 | }{ 177 | { 178 | name: "Send User Action:Success", 179 | ctx: context.Background(), 180 | in: &gengo.Action{ 181 | UserId: 1, 182 | Action: gengo.ActionEnum_LOGIN, 183 | }, 184 | want: &emptypb.Empty{}, 185 | wantErr: false, 186 | }, 187 | { 188 | name: "Send User Action:Success - full payload", 189 | ctx: context.Background(), 190 | in: &gengo.Action{ 191 | UserId: 1, 192 | Action: gengo.ActionEnum_LOGOUT, 193 | Timestamp: timestamppb.New(time.Now()), 194 | }, 195 | want: &emptypb.Empty{}, 196 | wantErr: false, 197 | }, 198 | { 199 | name: "Send User Action:Success - fail payload", 200 | ctx: context.Background(), 201 | in: &gengo.Action{ 202 | UserId: 1, 203 | Action: gengo.ActionEnum_VIEW_CART, 204 | Success: false, 205 | Error: "timeout on request", 206 | Timestamp: timestamppb.New(time.Now()), 207 | }, 208 | want: &emptypb.Empty{}, 209 | wantErr: false, 210 | }, 211 | { 212 | name: "Send User Action:Fail", 213 | ctx: context.Background(), 214 | in: &gengo.Action{ 215 | UserId: 1, 216 | }, 217 | want: nil, 218 | wantErr: true, 219 | }, 220 | } 221 | for _, tt := range tests { 222 | t.Run(tt.name, func(t *testing.T) { 223 | s := setupGrpc() 224 | got, err := s.SendUserAction(tt.ctx, tt.in) 225 | if (err != nil) != tt.wantErr { 226 | t.Errorf("Server.SendUserAction() error = %v, wantErr %v", err, tt.wantErr) 227 | return 228 | } 229 | if !reflect.DeepEqual(got, tt.want) { 230 | t.Errorf("Server.SendUserAction() = %v, want %v", got, tt.want) 231 | } 232 | }) 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /ex-4-data-contracts/server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "reflect" 6 | "testing" 7 | "time" 8 | 9 | gengo "github.com/soypete/Golang_datatools_exercises/ex-4-data-contracts/gen/go/proto" 10 | "google.golang.org/protobuf/types/known/emptypb" 11 | "google.golang.org/protobuf/types/known/timestamppb" 12 | ) 13 | 14 | func TestServer_UpdateUser(t *testing.T) { 15 | tests := []struct { 16 | name string 17 | ctx context.Context 18 | in *gengo.User 19 | want *emptypb.Empty 20 | wantErr bool 21 | }{ 22 | { 23 | name: "Update User:Success", 24 | ctx: context.Background(), 25 | in: &gengo.User{ 26 | Id: 1, 27 | Name: "SoyPete", 28 | Password: "password", 29 | Email: "captainnobody1@gmail.com", 30 | }, 31 | want: &emptypb.Empty{}, 32 | wantErr: false, 33 | }, 34 | { 35 | name: "Update User:Fail - Invalid Email", 36 | ctx: context.Background(), 37 | in: &gengo.User{ 38 | Id: 1, 39 | Name: "SoyPete", 40 | Email: "captainnobody1", 41 | Password: "password", 42 | }, 43 | want: nil, 44 | wantErr: true, 45 | }, 46 | { 47 | name: "Update User:Fail - No Password", 48 | ctx: context.Background(), 49 | in: &gengo.User{ 50 | Id: 1, 51 | Name: "SoyPete", 52 | Email: "captainnobody1@email.com", 53 | }, 54 | want: nil, 55 | wantErr: true, 56 | }, 57 | { 58 | name: "Update User:Fail - No Email", 59 | ctx: context.Background(), 60 | in: &gengo.User{ 61 | Id: 1, 62 | Name: "SoyPete", 63 | Password: "password", 64 | }, 65 | want: nil, 66 | wantErr: true, 67 | }, 68 | } 69 | for _, tt := range tests { 70 | t.Run(tt.name, func(t *testing.T) { 71 | s := setupServer() 72 | got, err := s.UpdateUser(tt.ctx, tt.in) 73 | if (err != nil) != tt.wantErr { 74 | t.Errorf("Server.UpdateUser() error = %v, wantErr %v", err, tt.wantErr) 75 | return 76 | } 77 | if !reflect.DeepEqual(got, tt.want) { 78 | t.Errorf("Server.UpdateUser() = %v, want %v", got, tt.want) 79 | } 80 | }) 81 | } 82 | } 83 | 84 | func TestServer_GetUserInfo(t *testing.T) { 85 | tests := []struct { 86 | name string 87 | ctx context.Context 88 | in *gengo.UserIdentifier 89 | want *gengo.User 90 | wantErr bool 91 | }{ 92 | { 93 | name: "Get User:Success", 94 | ctx: context.Background(), 95 | in: &gengo.UserIdentifier{ 96 | UserId: 1, 97 | }, 98 | want: &gengo.User{ 99 | Id: 1, 100 | Name: "SoyPete", 101 | Email: "captainnobody1@email.com", 102 | // Do not want to return password 103 | }, 104 | wantErr: false, 105 | }, 106 | { 107 | name: "Get User:Fail - Invalid ID", 108 | ctx: context.Background(), 109 | in: &gengo.UserIdentifier{}, 110 | want: nil, 111 | wantErr: true, 112 | }, 113 | } 114 | for _, tt := range tests { 115 | t.Run(tt.name, func(t *testing.T) { 116 | s := setupServer() 117 | got, err := s.GetUserInfo(tt.ctx, tt.in) 118 | if (err != nil) != tt.wantErr { 119 | t.Errorf("Server.GetUserInfo() error = %v, wantErr %v", err, tt.wantErr) 120 | return 121 | } 122 | if !reflect.DeepEqual(got, tt.want) { 123 | t.Errorf("Server.GetUserInfo() = %v, want %v", got, tt.want) 124 | } 125 | }) 126 | } 127 | } 128 | 129 | func TestServer_DeleteUser(t *testing.T) { 130 | tests := []struct { 131 | name string 132 | ctx context.Context 133 | in *gengo.UserIdentifier 134 | want *emptypb.Empty 135 | wantErr bool 136 | }{ 137 | { 138 | name: "Delete User:Success", 139 | ctx: context.Background(), 140 | in: &gengo.UserIdentifier{ 141 | UserId: 1, 142 | }, 143 | want: &emptypb.Empty{}, 144 | wantErr: false, 145 | }, 146 | { 147 | name: "Delete User:Fail - Invalid ID", 148 | ctx: context.Background(), 149 | in: &gengo.UserIdentifier{}, 150 | want: nil, 151 | wantErr: true, 152 | }, 153 | } 154 | for _, tt := range tests { 155 | t.Run(tt.name, func(t *testing.T) { 156 | s := setupServer() 157 | got, err := s.DeleteUser(tt.ctx, tt.in) 158 | if (err != nil) != tt.wantErr { 159 | t.Errorf("Server.DeleteUser() error = %v, wantErr %v", err, tt.wantErr) 160 | return 161 | } 162 | if !reflect.DeepEqual(got, tt.want) { 163 | t.Errorf("Server.DeleteUser() = %v, want %v", got, tt.want) 164 | } 165 | }) 166 | } 167 | } 168 | 169 | func TestServer_SendUserAction(t *testing.T) { 170 | tests := []struct { 171 | name string 172 | ctx context.Context 173 | in *gengo.Action 174 | want *emptypb.Empty 175 | wantErr bool 176 | }{ 177 | { 178 | name: "Send User Action:Success", 179 | ctx: context.Background(), 180 | in: &gengo.Action{ 181 | UserId: 1, 182 | Action: gengo.ActionEnum_LOGIN, 183 | }, 184 | want: &emptypb.Empty{}, 185 | wantErr: false, 186 | }, 187 | { 188 | name: "Send User Action:Success - full payload", 189 | ctx: context.Background(), 190 | in: &gengo.Action{ 191 | UserId: 1, 192 | Action: gengo.ActionEnum_LOGOUT, 193 | Timestamp: timestamppb.New(time.Now()), 194 | }, 195 | want: &emptypb.Empty{}, 196 | wantErr: false, 197 | }, 198 | { 199 | name: "Send User Action:Success - fail payload", 200 | ctx: context.Background(), 201 | in: &gengo.Action{ 202 | UserId: 1, 203 | Action: gengo.ActionEnum_VIEW_CART, 204 | Success: false, 205 | Error: "timeout on request", 206 | Timestamp: timestamppb.New(time.Now()), 207 | }, 208 | want: &emptypb.Empty{}, 209 | wantErr: false, 210 | }, 211 | { 212 | name: "Send User Action:Fail", 213 | ctx: context.Background(), 214 | in: &gengo.Action{ 215 | UserId: 1, 216 | }, 217 | want: nil, 218 | wantErr: true, 219 | }, 220 | } 221 | for _, tt := range tests { 222 | t.Run(tt.name, func(t *testing.T) { 223 | s := setupServer() 224 | got, err := s.SendUserAction(tt.ctx, tt.in) 225 | if (err != nil) != tt.wantErr { 226 | t.Errorf("Server.SendUserAction() error = %v, wantErr %v", err, tt.wantErr) 227 | return 228 | } 229 | if !reflect.DeepEqual(got, tt.want) { 230 | t.Errorf("Server.SendUserAction() = %v, want %v", got, tt.want) 231 | } 232 | }) 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /ex-4-data-contracts/solution/server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "reflect" 6 | "testing" 7 | "time" 8 | 9 | gengo "github.com/soypete/Golang_datatools_exercises/ex-4-data-contracts/gen/go/proto" 10 | "google.golang.org/protobuf/types/known/emptypb" 11 | "google.golang.org/protobuf/types/known/timestamppb" 12 | ) 13 | 14 | func TestServer_UpdateUser(t *testing.T) { 15 | tests := []struct { 16 | name string 17 | ctx context.Context 18 | in *gengo.User 19 | want *emptypb.Empty 20 | wantErr bool 21 | }{ 22 | { 23 | name: "Update User:Success", 24 | ctx: context.Background(), 25 | in: &gengo.User{ 26 | Id: 1, 27 | Name: "SoyPete", 28 | Password: "password", 29 | Email: "captainnobody1@gmail.com", 30 | }, 31 | want: &emptypb.Empty{}, 32 | wantErr: false, 33 | }, 34 | { 35 | name: "Update User:Fail - Invalid Email", 36 | ctx: context.Background(), 37 | in: &gengo.User{ 38 | Id: 1, 39 | Name: "SoyPete", 40 | Email: "captainnobody1", 41 | Password: "password", 42 | }, 43 | want: nil, 44 | wantErr: true, 45 | }, 46 | { 47 | name: "Update User:Fail - No Password", 48 | ctx: context.Background(), 49 | in: &gengo.User{ 50 | Id: 1, 51 | Name: "SoyPete", 52 | Email: "captainnobody1@email.com", 53 | }, 54 | want: nil, 55 | wantErr: true, 56 | }, 57 | { 58 | name: "Update User:Fail - No Email", 59 | ctx: context.Background(), 60 | in: &gengo.User{ 61 | Id: 1, 62 | Name: "SoyPete", 63 | Password: "password", 64 | }, 65 | want: nil, 66 | wantErr: true, 67 | }, 68 | } 69 | for _, tt := range tests { 70 | t.Run(tt.name, func(t *testing.T) { 71 | s := setupServer() 72 | got, err := s.UpdateUser(tt.ctx, tt.in) 73 | if (err != nil) != tt.wantErr { 74 | t.Errorf("Server.UpdateUser() error = %v, wantErr %v", err, tt.wantErr) 75 | return 76 | } 77 | if !reflect.DeepEqual(got, tt.want) { 78 | t.Errorf("Server.UpdateUser() = %v, want %v", got, tt.want) 79 | } 80 | }) 81 | } 82 | } 83 | 84 | func TestServer_GetUserInfo(t *testing.T) { 85 | tests := []struct { 86 | name string 87 | ctx context.Context 88 | in *gengo.UserIdentifier 89 | want *gengo.User 90 | wantErr bool 91 | }{ 92 | { 93 | name: "Get User:Success", 94 | ctx: context.Background(), 95 | in: &gengo.UserIdentifier{ 96 | UserId: 1, 97 | }, 98 | want: &gengo.User{ 99 | Id: 1, 100 | Name: "SoyPete", 101 | Email: "captainnobody1@email.com", 102 | // Do not want to return password 103 | }, 104 | wantErr: false, 105 | }, 106 | { 107 | name: "Get User:Fail - Invalid ID", 108 | ctx: context.Background(), 109 | in: &gengo.UserIdentifier{}, 110 | want: nil, 111 | wantErr: true, 112 | }, 113 | } 114 | for _, tt := range tests { 115 | t.Run(tt.name, func(t *testing.T) { 116 | s := setupServer() 117 | got, err := s.GetUserInfo(tt.ctx, tt.in) 118 | if (err != nil) != tt.wantErr { 119 | t.Errorf("Server.GetUserInfo() error = %v, wantErr %v", err, tt.wantErr) 120 | return 121 | } 122 | if !reflect.DeepEqual(got, tt.want) { 123 | t.Errorf("Server.GetUserInfo() = %v, want %v", got, tt.want) 124 | } 125 | }) 126 | } 127 | } 128 | 129 | func TestServer_DeleteUser(t *testing.T) { 130 | tests := []struct { 131 | name string 132 | ctx context.Context 133 | in *gengo.UserIdentifier 134 | want *emptypb.Empty 135 | wantErr bool 136 | }{ 137 | { 138 | name: "Delete User:Success", 139 | ctx: context.Background(), 140 | in: &gengo.UserIdentifier{ 141 | UserId: 1, 142 | }, 143 | want: &emptypb.Empty{}, 144 | wantErr: false, 145 | }, 146 | { 147 | name: "Delete User:Fail - Invalid ID", 148 | ctx: context.Background(), 149 | in: &gengo.UserIdentifier{}, 150 | want: nil, 151 | wantErr: true, 152 | }, 153 | } 154 | for _, tt := range tests { 155 | t.Run(tt.name, func(t *testing.T) { 156 | s := setupServer() 157 | got, err := s.DeleteUser(tt.ctx, tt.in) 158 | if (err != nil) != tt.wantErr { 159 | t.Errorf("Server.DeleteUser() error = %v, wantErr %v", err, tt.wantErr) 160 | return 161 | } 162 | if !reflect.DeepEqual(got, tt.want) { 163 | t.Errorf("Server.DeleteUser() = %v, want %v", got, tt.want) 164 | } 165 | }) 166 | } 167 | } 168 | 169 | func TestServer_SendUserAction(t *testing.T) { 170 | tests := []struct { 171 | name string 172 | ctx context.Context 173 | in *gengo.Action 174 | want *emptypb.Empty 175 | wantErr bool 176 | }{ 177 | { 178 | name: "Send User Action:Success", 179 | ctx: context.Background(), 180 | in: &gengo.Action{ 181 | UserId: 1, 182 | Action: gengo.ActionEnum_LOGIN, 183 | }, 184 | want: &emptypb.Empty{}, 185 | wantErr: false, 186 | }, 187 | { 188 | name: "Send User Action:Success - full payload", 189 | ctx: context.Background(), 190 | in: &gengo.Action{ 191 | UserId: 1, 192 | Action: gengo.ActionEnum_LOGOUT, 193 | Timestamp: timestamppb.New(time.Now()), 194 | }, 195 | want: &emptypb.Empty{}, 196 | wantErr: false, 197 | }, 198 | { 199 | name: "Send User Action:Success - fail payload", 200 | ctx: context.Background(), 201 | in: &gengo.Action{ 202 | UserId: 1, 203 | Action: gengo.ActionEnum_VIEW_CART, 204 | Success: false, 205 | Error: "timeout on request", 206 | Timestamp: timestamppb.New(time.Now()), 207 | }, 208 | want: &emptypb.Empty{}, 209 | wantErr: false, 210 | }, 211 | { 212 | name: "Send User Action:Fail", 213 | ctx: context.Background(), 214 | in: &gengo.Action{ 215 | UserId: 1, 216 | }, 217 | want: nil, 218 | wantErr: true, 219 | }, 220 | } 221 | for _, tt := range tests { 222 | t.Run(tt.name, func(t *testing.T) { 223 | s := setupServer() 224 | got, err := s.SendUserAction(tt.ctx, tt.in) 225 | if (err != nil) != tt.wantErr { 226 | t.Errorf("Server.SendUserAction() error = %v, wantErr %v", err, tt.wantErr) 227 | return 228 | } 229 | if !reflect.DeepEqual(got, tt.want) { 230 | t.Errorf("Server.SendUserAction() = %v, want %v", got, tt.want) 231 | } 232 | }) 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 2 | github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 3 | github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= 4 | github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= 5 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 6 | github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= 7 | github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 8 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 9 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 10 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 11 | github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= 12 | github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 13 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= 14 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= 15 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= 16 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= 17 | github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= 18 | github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 19 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= 20 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 21 | github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= 22 | github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= 23 | github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= 24 | github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= 25 | github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= 26 | github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= 27 | github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= 28 | github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 29 | github.com/pressly/goose/v3 v3.15.1 h1:dKaJ1SdLvS/+HtS8PzFT0KBEtICC1jewLXM+b3emlv8= 30 | github.com/pressly/goose/v3 v3.15.1/go.mod h1:0E3Yg/+EwYzO6Rz2P98MlClFgIcoujbVRs575yi3iIM= 31 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= 32 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= 33 | github.com/soypete/WebServices-in-3-weeks v0.0.0-20231015040516-f9017a42446c h1:4XMLGG4XlIqi63XkSrF5TV99KCjZ1QfmN0EthXjPTHQ= 34 | github.com/soypete/WebServices-in-3-weeks v0.0.0-20231015040516-f9017a42446c/go.mod h1:G1uggQzpZn33XAufQIhfXnLh0PhKlSU75qVINyt7KT0= 35 | golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= 36 | golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= 37 | golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= 38 | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 39 | golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= 40 | golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= 41 | golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= 42 | golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 43 | golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= 44 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 45 | golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= 46 | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= 47 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 48 | google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= 49 | google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= 50 | google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= 51 | google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= 52 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= 53 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= 54 | google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= 55 | google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= 56 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 57 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 58 | google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= 59 | google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 60 | lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= 61 | lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= 62 | modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= 63 | modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= 64 | modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0= 65 | modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= 66 | modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= 67 | modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak= 68 | modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= 69 | modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= 70 | modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= 71 | modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= 72 | modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= 73 | modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= 74 | modernc.org/sqlite v1.26.0 h1:SocQdLRSYlA8W99V8YH0NES75thx19d9sB/aFc4R8Lw= 75 | modernc.org/sqlite v1.26.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU= 76 | modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= 77 | modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= 78 | modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= 79 | modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= 80 | -------------------------------------------------------------------------------- /grpc-gateway-demo/gen/proto/user_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | 3 | package _go 4 | 5 | import ( 6 | context "context" 7 | grpc "google.golang.org/grpc" 8 | codes "google.golang.org/grpc/codes" 9 | status "google.golang.org/grpc/status" 10 | emptypb "google.golang.org/protobuf/types/known/emptypb" 11 | ) 12 | 13 | // This is a compile-time assertion to ensure that this generated file 14 | // is compatible with the grpc package it is being compiled against. 15 | // Requires gRPC-Go v1.32.0 or later. 16 | const _ = grpc.SupportPackageIsVersion7 17 | 18 | // UserActionClient is the client API for UserAction service. 19 | // 20 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 21 | type UserActionClient interface { 22 | UpdateUser(ctx context.Context, in *User, opts ...grpc.CallOption) (*emptypb.Empty, error) 23 | GetUserInfo(ctx context.Context, in *UserIdentifier, opts ...grpc.CallOption) (*User, error) 24 | DeleteUser(ctx context.Context, in *UserIdentifier, opts ...grpc.CallOption) (*emptypb.Empty, error) 25 | SendUserAction(ctx context.Context, in *Action, opts ...grpc.CallOption) (*emptypb.Empty, error) 26 | } 27 | 28 | type userActionClient struct { 29 | cc grpc.ClientConnInterface 30 | } 31 | 32 | func NewUserActionClient(cc grpc.ClientConnInterface) UserActionClient { 33 | return &userActionClient{cc} 34 | } 35 | 36 | func (c *userActionClient) UpdateUser(ctx context.Context, in *User, opts ...grpc.CallOption) (*emptypb.Empty, error) { 37 | out := new(emptypb.Empty) 38 | err := c.cc.Invoke(ctx, "/user.UserAction/UpdateUser", in, out, opts...) 39 | if err != nil { 40 | return nil, err 41 | } 42 | return out, nil 43 | } 44 | 45 | func (c *userActionClient) GetUserInfo(ctx context.Context, in *UserIdentifier, opts ...grpc.CallOption) (*User, error) { 46 | out := new(User) 47 | err := c.cc.Invoke(ctx, "/user.UserAction/GetUserInfo", in, out, opts...) 48 | if err != nil { 49 | return nil, err 50 | } 51 | return out, nil 52 | } 53 | 54 | func (c *userActionClient) DeleteUser(ctx context.Context, in *UserIdentifier, opts ...grpc.CallOption) (*emptypb.Empty, error) { 55 | out := new(emptypb.Empty) 56 | err := c.cc.Invoke(ctx, "/user.UserAction/DeleteUser", in, out, opts...) 57 | if err != nil { 58 | return nil, err 59 | } 60 | return out, nil 61 | } 62 | 63 | func (c *userActionClient) SendUserAction(ctx context.Context, in *Action, opts ...grpc.CallOption) (*emptypb.Empty, error) { 64 | out := new(emptypb.Empty) 65 | err := c.cc.Invoke(ctx, "/user.UserAction/SendUserAction", in, out, opts...) 66 | if err != nil { 67 | return nil, err 68 | } 69 | return out, nil 70 | } 71 | 72 | // UserActionServer is the server API for UserAction service. 73 | // All implementations should embed UnimplementedUserActionServer 74 | // for forward compatibility 75 | type UserActionServer interface { 76 | UpdateUser(context.Context, *User) (*emptypb.Empty, error) 77 | GetUserInfo(context.Context, *UserIdentifier) (*User, error) 78 | DeleteUser(context.Context, *UserIdentifier) (*emptypb.Empty, error) 79 | SendUserAction(context.Context, *Action) (*emptypb.Empty, error) 80 | } 81 | 82 | // UnimplementedUserActionServer should be embedded to have forward compatible implementations. 83 | type UnimplementedUserActionServer struct { 84 | } 85 | 86 | func (UnimplementedUserActionServer) UpdateUser(context.Context, *User) (*emptypb.Empty, error) { 87 | return nil, status.Errorf(codes.Unimplemented, "method UpdateUser not implemented") 88 | } 89 | func (UnimplementedUserActionServer) GetUserInfo(context.Context, *UserIdentifier) (*User, error) { 90 | return nil, status.Errorf(codes.Unimplemented, "method GetUserInfo not implemented") 91 | } 92 | func (UnimplementedUserActionServer) DeleteUser(context.Context, *UserIdentifier) (*emptypb.Empty, error) { 93 | return nil, status.Errorf(codes.Unimplemented, "method DeleteUser not implemented") 94 | } 95 | func (UnimplementedUserActionServer) SendUserAction(context.Context, *Action) (*emptypb.Empty, error) { 96 | return nil, status.Errorf(codes.Unimplemented, "method SendUserAction not implemented") 97 | } 98 | 99 | // UnsafeUserActionServer may be embedded to opt out of forward compatibility for this service. 100 | // Use of this interface is not recommended, as added methods to UserActionServer will 101 | // result in compilation errors. 102 | type UnsafeUserActionServer interface { 103 | mustEmbedUnimplementedUserActionServer() 104 | } 105 | 106 | func RegisterUserActionServer(s grpc.ServiceRegistrar, srv UserActionServer) { 107 | s.RegisterService(&UserAction_ServiceDesc, srv) 108 | } 109 | 110 | func _UserAction_UpdateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 111 | in := new(User) 112 | if err := dec(in); err != nil { 113 | return nil, err 114 | } 115 | if interceptor == nil { 116 | return srv.(UserActionServer).UpdateUser(ctx, in) 117 | } 118 | info := &grpc.UnaryServerInfo{ 119 | Server: srv, 120 | FullMethod: "/user.UserAction/UpdateUser", 121 | } 122 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 123 | return srv.(UserActionServer).UpdateUser(ctx, req.(*User)) 124 | } 125 | return interceptor(ctx, in, info, handler) 126 | } 127 | 128 | func _UserAction_GetUserInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 129 | in := new(UserIdentifier) 130 | if err := dec(in); err != nil { 131 | return nil, err 132 | } 133 | if interceptor == nil { 134 | return srv.(UserActionServer).GetUserInfo(ctx, in) 135 | } 136 | info := &grpc.UnaryServerInfo{ 137 | Server: srv, 138 | FullMethod: "/user.UserAction/GetUserInfo", 139 | } 140 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 141 | return srv.(UserActionServer).GetUserInfo(ctx, req.(*UserIdentifier)) 142 | } 143 | return interceptor(ctx, in, info, handler) 144 | } 145 | 146 | func _UserAction_DeleteUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 147 | in := new(UserIdentifier) 148 | if err := dec(in); err != nil { 149 | return nil, err 150 | } 151 | if interceptor == nil { 152 | return srv.(UserActionServer).DeleteUser(ctx, in) 153 | } 154 | info := &grpc.UnaryServerInfo{ 155 | Server: srv, 156 | FullMethod: "/user.UserAction/DeleteUser", 157 | } 158 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 159 | return srv.(UserActionServer).DeleteUser(ctx, req.(*UserIdentifier)) 160 | } 161 | return interceptor(ctx, in, info, handler) 162 | } 163 | 164 | func _UserAction_SendUserAction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 165 | in := new(Action) 166 | if err := dec(in); err != nil { 167 | return nil, err 168 | } 169 | if interceptor == nil { 170 | return srv.(UserActionServer).SendUserAction(ctx, in) 171 | } 172 | info := &grpc.UnaryServerInfo{ 173 | Server: srv, 174 | FullMethod: "/user.UserAction/SendUserAction", 175 | } 176 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 177 | return srv.(UserActionServer).SendUserAction(ctx, req.(*Action)) 178 | } 179 | return interceptor(ctx, in, info, handler) 180 | } 181 | 182 | // UserAction_ServiceDesc is the grpc.ServiceDesc for UserAction service. 183 | // It's only intended for direct use with grpc.RegisterService, 184 | // and not to be introspected or modified (even as a copy) 185 | var UserAction_ServiceDesc = grpc.ServiceDesc{ 186 | ServiceName: "user.UserAction", 187 | HandlerType: (*UserActionServer)(nil), 188 | Methods: []grpc.MethodDesc{ 189 | { 190 | MethodName: "UpdateUser", 191 | Handler: _UserAction_UpdateUser_Handler, 192 | }, 193 | { 194 | MethodName: "GetUserInfo", 195 | Handler: _UserAction_GetUserInfo_Handler, 196 | }, 197 | { 198 | MethodName: "DeleteUser", 199 | Handler: _UserAction_DeleteUser_Handler, 200 | }, 201 | { 202 | MethodName: "SendUserAction", 203 | Handler: _UserAction_SendUserAction_Handler, 204 | }, 205 | }, 206 | Streams: []grpc.StreamDesc{}, 207 | Metadata: "proto/user.proto", 208 | } 209 | -------------------------------------------------------------------------------- /ex-4-data-contracts/gen/go/proto/user_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | 3 | package _go 4 | 5 | import ( 6 | context "context" 7 | grpc "google.golang.org/grpc" 8 | codes "google.golang.org/grpc/codes" 9 | status "google.golang.org/grpc/status" 10 | emptypb "google.golang.org/protobuf/types/known/emptypb" 11 | ) 12 | 13 | // This is a compile-time assertion to ensure that this generated file 14 | // is compatible with the grpc package it is being compiled against. 15 | // Requires gRPC-Go v1.32.0 or later. 16 | const _ = grpc.SupportPackageIsVersion7 17 | 18 | // UserActionClient is the client API for UserAction service. 19 | // 20 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 21 | type UserActionClient interface { 22 | UpdateUser(ctx context.Context, in *User, opts ...grpc.CallOption) (*emptypb.Empty, error) 23 | GetUserInfo(ctx context.Context, in *UserIdentifier, opts ...grpc.CallOption) (*User, error) 24 | DeleteUser(ctx context.Context, in *UserIdentifier, opts ...grpc.CallOption) (*emptypb.Empty, error) 25 | SendUserAction(ctx context.Context, in *Action, opts ...grpc.CallOption) (*emptypb.Empty, error) 26 | } 27 | 28 | type userActionClient struct { 29 | cc grpc.ClientConnInterface 30 | } 31 | 32 | func NewUserActionClient(cc grpc.ClientConnInterface) UserActionClient { 33 | return &userActionClient{cc} 34 | } 35 | 36 | func (c *userActionClient) UpdateUser(ctx context.Context, in *User, opts ...grpc.CallOption) (*emptypb.Empty, error) { 37 | out := new(emptypb.Empty) 38 | err := c.cc.Invoke(ctx, "/user.UserAction/UpdateUser", in, out, opts...) 39 | if err != nil { 40 | return nil, err 41 | } 42 | return out, nil 43 | } 44 | 45 | func (c *userActionClient) GetUserInfo(ctx context.Context, in *UserIdentifier, opts ...grpc.CallOption) (*User, error) { 46 | out := new(User) 47 | err := c.cc.Invoke(ctx, "/user.UserAction/GetUserInfo", in, out, opts...) 48 | if err != nil { 49 | return nil, err 50 | } 51 | return out, nil 52 | } 53 | 54 | func (c *userActionClient) DeleteUser(ctx context.Context, in *UserIdentifier, opts ...grpc.CallOption) (*emptypb.Empty, error) { 55 | out := new(emptypb.Empty) 56 | err := c.cc.Invoke(ctx, "/user.UserAction/DeleteUser", in, out, opts...) 57 | if err != nil { 58 | return nil, err 59 | } 60 | return out, nil 61 | } 62 | 63 | func (c *userActionClient) SendUserAction(ctx context.Context, in *Action, opts ...grpc.CallOption) (*emptypb.Empty, error) { 64 | out := new(emptypb.Empty) 65 | err := c.cc.Invoke(ctx, "/user.UserAction/SendUserAction", in, out, opts...) 66 | if err != nil { 67 | return nil, err 68 | } 69 | return out, nil 70 | } 71 | 72 | // UserActionServer is the server API for UserAction service. 73 | // All implementations should embed UnimplementedUserActionServer 74 | // for forward compatibility 75 | type UserActionServer interface { 76 | UpdateUser(context.Context, *User) (*emptypb.Empty, error) 77 | GetUserInfo(context.Context, *UserIdentifier) (*User, error) 78 | DeleteUser(context.Context, *UserIdentifier) (*emptypb.Empty, error) 79 | SendUserAction(context.Context, *Action) (*emptypb.Empty, error) 80 | } 81 | 82 | // UnimplementedUserActionServer should be embedded to have forward compatible implementations. 83 | type UnimplementedUserActionServer struct { 84 | } 85 | 86 | func (UnimplementedUserActionServer) UpdateUser(context.Context, *User) (*emptypb.Empty, error) { 87 | return nil, status.Errorf(codes.Unimplemented, "method UpdateUser not implemented") 88 | } 89 | func (UnimplementedUserActionServer) GetUserInfo(context.Context, *UserIdentifier) (*User, error) { 90 | return nil, status.Errorf(codes.Unimplemented, "method GetUserInfo not implemented") 91 | } 92 | func (UnimplementedUserActionServer) DeleteUser(context.Context, *UserIdentifier) (*emptypb.Empty, error) { 93 | return nil, status.Errorf(codes.Unimplemented, "method DeleteUser not implemented") 94 | } 95 | func (UnimplementedUserActionServer) SendUserAction(context.Context, *Action) (*emptypb.Empty, error) { 96 | return nil, status.Errorf(codes.Unimplemented, "method SendUserAction not implemented") 97 | } 98 | 99 | // UnsafeUserActionServer may be embedded to opt out of forward compatibility for this service. 100 | // Use of this interface is not recommended, as added methods to UserActionServer will 101 | // result in compilation errors. 102 | type UnsafeUserActionServer interface { 103 | mustEmbedUnimplementedUserActionServer() 104 | } 105 | 106 | func RegisterUserActionServer(s grpc.ServiceRegistrar, srv UserActionServer) { 107 | s.RegisterService(&UserAction_ServiceDesc, srv) 108 | } 109 | 110 | func _UserAction_UpdateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 111 | in := new(User) 112 | if err := dec(in); err != nil { 113 | return nil, err 114 | } 115 | if interceptor == nil { 116 | return srv.(UserActionServer).UpdateUser(ctx, in) 117 | } 118 | info := &grpc.UnaryServerInfo{ 119 | Server: srv, 120 | FullMethod: "/user.UserAction/UpdateUser", 121 | } 122 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 123 | return srv.(UserActionServer).UpdateUser(ctx, req.(*User)) 124 | } 125 | return interceptor(ctx, in, info, handler) 126 | } 127 | 128 | func _UserAction_GetUserInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 129 | in := new(UserIdentifier) 130 | if err := dec(in); err != nil { 131 | return nil, err 132 | } 133 | if interceptor == nil { 134 | return srv.(UserActionServer).GetUserInfo(ctx, in) 135 | } 136 | info := &grpc.UnaryServerInfo{ 137 | Server: srv, 138 | FullMethod: "/user.UserAction/GetUserInfo", 139 | } 140 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 141 | return srv.(UserActionServer).GetUserInfo(ctx, req.(*UserIdentifier)) 142 | } 143 | return interceptor(ctx, in, info, handler) 144 | } 145 | 146 | func _UserAction_DeleteUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 147 | in := new(UserIdentifier) 148 | if err := dec(in); err != nil { 149 | return nil, err 150 | } 151 | if interceptor == nil { 152 | return srv.(UserActionServer).DeleteUser(ctx, in) 153 | } 154 | info := &grpc.UnaryServerInfo{ 155 | Server: srv, 156 | FullMethod: "/user.UserAction/DeleteUser", 157 | } 158 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 159 | return srv.(UserActionServer).DeleteUser(ctx, req.(*UserIdentifier)) 160 | } 161 | return interceptor(ctx, in, info, handler) 162 | } 163 | 164 | func _UserAction_SendUserAction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 165 | in := new(Action) 166 | if err := dec(in); err != nil { 167 | return nil, err 168 | } 169 | if interceptor == nil { 170 | return srv.(UserActionServer).SendUserAction(ctx, in) 171 | } 172 | info := &grpc.UnaryServerInfo{ 173 | Server: srv, 174 | FullMethod: "/user.UserAction/SendUserAction", 175 | } 176 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 177 | return srv.(UserActionServer).SendUserAction(ctx, req.(*Action)) 178 | } 179 | return interceptor(ctx, in, info, handler) 180 | } 181 | 182 | // UserAction_ServiceDesc is the grpc.ServiceDesc for UserAction service. 183 | // It's only intended for direct use with grpc.RegisterService, 184 | // and not to be introspected or modified (even as a copy) 185 | var UserAction_ServiceDesc = grpc.ServiceDesc{ 186 | ServiceName: "user.UserAction", 187 | HandlerType: (*UserActionServer)(nil), 188 | Methods: []grpc.MethodDesc{ 189 | { 190 | MethodName: "UpdateUser", 191 | Handler: _UserAction_UpdateUser_Handler, 192 | }, 193 | { 194 | MethodName: "GetUserInfo", 195 | Handler: _UserAction_GetUserInfo_Handler, 196 | }, 197 | { 198 | MethodName: "DeleteUser", 199 | Handler: _UserAction_DeleteUser_Handler, 200 | }, 201 | { 202 | MethodName: "SendUserAction", 203 | Handler: _UserAction_SendUserAction_Handler, 204 | }, 205 | }, 206 | Streams: []grpc.StreamDesc{}, 207 | Metadata: "proto/user.proto", 208 | } 209 | -------------------------------------------------------------------------------- /ex-4-data-contracts/gen/go/proto/user.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.27.1 4 | // protoc (unknown) 5 | // source: proto/user.proto 6 | 7 | package _go 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | emptypb "google.golang.org/protobuf/types/known/emptypb" 13 | timestamppb "google.golang.org/protobuf/types/known/timestamppb" 14 | reflect "reflect" 15 | sync "sync" 16 | ) 17 | 18 | const ( 19 | // Verify that this generated code is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 21 | // Verify that runtime/protoimpl is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 23 | ) 24 | 25 | type ActionEnum int32 26 | 27 | const ( 28 | ActionEnum_DEFAULT ActionEnum = 0 29 | ActionEnum_LOGIN ActionEnum = 1 30 | ActionEnum_LOGOUT ActionEnum = 2 31 | ActionEnum_PURCHASE ActionEnum = 3 32 | ActionEnum_RETURN ActionEnum = 4 33 | ActionEnum_ADD_TO_CART ActionEnum = 5 34 | ActionEnum_REMOVE_FROM_CART ActionEnum = 6 35 | ActionEnum_VIEW_ITEM ActionEnum = 7 36 | ActionEnum_VIEW_CART ActionEnum = 8 37 | ActionEnum_VIEW_PURCHASE_HISTORY ActionEnum = 9 38 | ) 39 | 40 | // Enum value maps for ActionEnum. 41 | var ( 42 | ActionEnum_name = map[int32]string{ 43 | 0: "DEFAULT", 44 | 1: "LOGIN", 45 | 2: "LOGOUT", 46 | 3: "PURCHASE", 47 | 4: "RETURN", 48 | 5: "ADD_TO_CART", 49 | 6: "REMOVE_FROM_CART", 50 | 7: "VIEW_ITEM", 51 | 8: "VIEW_CART", 52 | 9: "VIEW_PURCHASE_HISTORY", 53 | } 54 | ActionEnum_value = map[string]int32{ 55 | "DEFAULT": 0, 56 | "LOGIN": 1, 57 | "LOGOUT": 2, 58 | "PURCHASE": 3, 59 | "RETURN": 4, 60 | "ADD_TO_CART": 5, 61 | "REMOVE_FROM_CART": 6, 62 | "VIEW_ITEM": 7, 63 | "VIEW_CART": 8, 64 | "VIEW_PURCHASE_HISTORY": 9, 65 | } 66 | ) 67 | 68 | func (x ActionEnum) Enum() *ActionEnum { 69 | p := new(ActionEnum) 70 | *p = x 71 | return p 72 | } 73 | 74 | func (x ActionEnum) String() string { 75 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 76 | } 77 | 78 | func (ActionEnum) Descriptor() protoreflect.EnumDescriptor { 79 | return file_proto_user_proto_enumTypes[0].Descriptor() 80 | } 81 | 82 | func (ActionEnum) Type() protoreflect.EnumType { 83 | return &file_proto_user_proto_enumTypes[0] 84 | } 85 | 86 | func (x ActionEnum) Number() protoreflect.EnumNumber { 87 | return protoreflect.EnumNumber(x) 88 | } 89 | 90 | // Deprecated: Use ActionEnum.Descriptor instead. 91 | func (ActionEnum) EnumDescriptor() ([]byte, []int) { 92 | return file_proto_user_proto_rawDescGZIP(), []int{0} 93 | } 94 | 95 | type UserIdentifier struct { 96 | state protoimpl.MessageState 97 | sizeCache protoimpl.SizeCache 98 | unknownFields protoimpl.UnknownFields 99 | 100 | UserId int32 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` 101 | } 102 | 103 | func (x *UserIdentifier) Reset() { 104 | *x = UserIdentifier{} 105 | if protoimpl.UnsafeEnabled { 106 | mi := &file_proto_user_proto_msgTypes[0] 107 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 108 | ms.StoreMessageInfo(mi) 109 | } 110 | } 111 | 112 | func (x *UserIdentifier) String() string { 113 | return protoimpl.X.MessageStringOf(x) 114 | } 115 | 116 | func (*UserIdentifier) ProtoMessage() {} 117 | 118 | func (x *UserIdentifier) ProtoReflect() protoreflect.Message { 119 | mi := &file_proto_user_proto_msgTypes[0] 120 | if protoimpl.UnsafeEnabled && x != nil { 121 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 122 | if ms.LoadMessageInfo() == nil { 123 | ms.StoreMessageInfo(mi) 124 | } 125 | return ms 126 | } 127 | return mi.MessageOf(x) 128 | } 129 | 130 | // Deprecated: Use UserIdentifier.ProtoReflect.Descriptor instead. 131 | func (*UserIdentifier) Descriptor() ([]byte, []int) { 132 | return file_proto_user_proto_rawDescGZIP(), []int{0} 133 | } 134 | 135 | func (x *UserIdentifier) GetUserId() int32 { 136 | if x != nil { 137 | return x.UserId 138 | } 139 | return 0 140 | } 141 | 142 | type User struct { 143 | state protoimpl.MessageState 144 | sizeCache protoimpl.SizeCache 145 | unknownFields protoimpl.UnknownFields 146 | 147 | Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 148 | Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` 149 | Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"` 150 | Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"` 151 | } 152 | 153 | func (x *User) Reset() { 154 | *x = User{} 155 | if protoimpl.UnsafeEnabled { 156 | mi := &file_proto_user_proto_msgTypes[1] 157 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 158 | ms.StoreMessageInfo(mi) 159 | } 160 | } 161 | 162 | func (x *User) String() string { 163 | return protoimpl.X.MessageStringOf(x) 164 | } 165 | 166 | func (*User) ProtoMessage() {} 167 | 168 | func (x *User) ProtoReflect() protoreflect.Message { 169 | mi := &file_proto_user_proto_msgTypes[1] 170 | if protoimpl.UnsafeEnabled && x != nil { 171 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 172 | if ms.LoadMessageInfo() == nil { 173 | ms.StoreMessageInfo(mi) 174 | } 175 | return ms 176 | } 177 | return mi.MessageOf(x) 178 | } 179 | 180 | // Deprecated: Use User.ProtoReflect.Descriptor instead. 181 | func (*User) Descriptor() ([]byte, []int) { 182 | return file_proto_user_proto_rawDescGZIP(), []int{1} 183 | } 184 | 185 | func (x *User) GetId() int32 { 186 | if x != nil { 187 | return x.Id 188 | } 189 | return 0 190 | } 191 | 192 | func (x *User) GetName() string { 193 | if x != nil { 194 | return x.Name 195 | } 196 | return "" 197 | } 198 | 199 | func (x *User) GetEmail() string { 200 | if x != nil { 201 | return x.Email 202 | } 203 | return "" 204 | } 205 | 206 | func (x *User) GetPassword() string { 207 | if x != nil { 208 | return x.Password 209 | } 210 | return "" 211 | } 212 | 213 | type Action struct { 214 | state protoimpl.MessageState 215 | sizeCache protoimpl.SizeCache 216 | unknownFields protoimpl.UnknownFields 217 | 218 | UserId int32 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` 219 | Action ActionEnum `protobuf:"varint,2,opt,name=action,proto3,enum=user.ActionEnum" json:"action,omitempty"` 220 | Success bool `protobuf:"varint,3,opt,name=success,proto3" json:"success,omitempty"` 221 | Error string `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"` 222 | Timestamp *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` 223 | } 224 | 225 | func (x *Action) Reset() { 226 | *x = Action{} 227 | if protoimpl.UnsafeEnabled { 228 | mi := &file_proto_user_proto_msgTypes[2] 229 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 230 | ms.StoreMessageInfo(mi) 231 | } 232 | } 233 | 234 | func (x *Action) String() string { 235 | return protoimpl.X.MessageStringOf(x) 236 | } 237 | 238 | func (*Action) ProtoMessage() {} 239 | 240 | func (x *Action) ProtoReflect() protoreflect.Message { 241 | mi := &file_proto_user_proto_msgTypes[2] 242 | if protoimpl.UnsafeEnabled && x != nil { 243 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 244 | if ms.LoadMessageInfo() == nil { 245 | ms.StoreMessageInfo(mi) 246 | } 247 | return ms 248 | } 249 | return mi.MessageOf(x) 250 | } 251 | 252 | // Deprecated: Use Action.ProtoReflect.Descriptor instead. 253 | func (*Action) Descriptor() ([]byte, []int) { 254 | return file_proto_user_proto_rawDescGZIP(), []int{2} 255 | } 256 | 257 | func (x *Action) GetUserId() int32 { 258 | if x != nil { 259 | return x.UserId 260 | } 261 | return 0 262 | } 263 | 264 | func (x *Action) GetAction() ActionEnum { 265 | if x != nil { 266 | return x.Action 267 | } 268 | return ActionEnum_DEFAULT 269 | } 270 | 271 | func (x *Action) GetSuccess() bool { 272 | if x != nil { 273 | return x.Success 274 | } 275 | return false 276 | } 277 | 278 | func (x *Action) GetError() string { 279 | if x != nil { 280 | return x.Error 281 | } 282 | return "" 283 | } 284 | 285 | func (x *Action) GetTimestamp() *timestamppb.Timestamp { 286 | if x != nil { 287 | return x.Timestamp 288 | } 289 | return nil 290 | } 291 | 292 | var File_proto_user_proto protoreflect.FileDescriptor 293 | 294 | var file_proto_user_proto_rawDesc = []byte{ 295 | 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 296 | 0x74, 0x6f, 0x12, 0x04, 0x75, 0x73, 0x65, 0x72, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 297 | 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 298 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 299 | 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 300 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x29, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 301 | 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 302 | 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 303 | 0x64, 0x22, 0x5c, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 304 | 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 305 | 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 306 | 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 307 | 0x61, 0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 308 | 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 309 | 0xb5, 0x01, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 310 | 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x75, 0x73, 0x65, 311 | 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 312 | 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 313 | 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 314 | 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 315 | 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 316 | 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x38, 0x0a, 317 | 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 318 | 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 319 | 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 320 | 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2a, 0xaa, 0x01, 0x0a, 0x0a, 0x41, 0x63, 0x74, 0x69, 321 | 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 322 | 0x54, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x4f, 0x47, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0a, 323 | 0x0a, 0x06, 0x4c, 0x4f, 0x47, 0x4f, 0x55, 0x54, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x55, 324 | 0x52, 0x43, 0x48, 0x41, 0x53, 0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x54, 0x55, 325 | 0x52, 0x4e, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x44, 0x44, 0x5f, 0x54, 0x4f, 0x5f, 0x43, 326 | 0x41, 0x52, 0x54, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 327 | 0x46, 0x52, 0x4f, 0x4d, 0x5f, 0x43, 0x41, 0x52, 0x54, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x56, 328 | 0x49, 0x45, 0x57, 0x5f, 0x49, 0x54, 0x45, 0x4d, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x56, 0x49, 329 | 0x45, 0x57, 0x5f, 0x43, 0x41, 0x52, 0x54, 0x10, 0x08, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x49, 0x45, 330 | 0x57, 0x5f, 0x50, 0x55, 0x52, 0x43, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 331 | 0x52, 0x59, 0x10, 0x09, 0x32, 0xeb, 0x01, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x74, 332 | 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 333 | 0x72, 0x12, 0x0a, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x16, 0x2e, 334 | 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 335 | 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 336 | 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 337 | 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0x0a, 0x2e, 0x75, 338 | 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0a, 0x44, 0x65, 339 | 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x14, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 340 | 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0x16, 341 | 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 342 | 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x0e, 0x53, 0x65, 0x6e, 0x64, 343 | 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0c, 0x2e, 0x75, 0x73, 0x65, 344 | 0x72, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 345 | 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 346 | 0x22, 0x00, 0x42, 0x50, 0x5a, 0x4e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 347 | 0x2f, 0x53, 0x6f, 0x79, 0x70, 0x65, 0x74, 0x65, 0x2f, 0x47, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x5f, 348 | 0x64, 0x61, 0x74, 0x61, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x5f, 0x65, 0x78, 0x65, 0x72, 0x63, 0x69, 349 | 0x73, 0x65, 0x73, 0x2f, 0x65, 0x78, 0x2d, 0x34, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x63, 0x6f, 350 | 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 351 | 0x6e, 0x2f, 0x67, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 352 | } 353 | 354 | var ( 355 | file_proto_user_proto_rawDescOnce sync.Once 356 | file_proto_user_proto_rawDescData = file_proto_user_proto_rawDesc 357 | ) 358 | 359 | func file_proto_user_proto_rawDescGZIP() []byte { 360 | file_proto_user_proto_rawDescOnce.Do(func() { 361 | file_proto_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_user_proto_rawDescData) 362 | }) 363 | return file_proto_user_proto_rawDescData 364 | } 365 | 366 | var file_proto_user_proto_enumTypes = make([]protoimpl.EnumInfo, 1) 367 | var file_proto_user_proto_msgTypes = make([]protoimpl.MessageInfo, 3) 368 | var file_proto_user_proto_goTypes = []interface{}{ 369 | (ActionEnum)(0), // 0: user.ActionEnum 370 | (*UserIdentifier)(nil), // 1: user.UserIdentifier 371 | (*User)(nil), // 2: user.User 372 | (*Action)(nil), // 3: user.Action 373 | (*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp 374 | (*emptypb.Empty)(nil), // 5: google.protobuf.Empty 375 | } 376 | var file_proto_user_proto_depIdxs = []int32{ 377 | 0, // 0: user.Action.action:type_name -> user.ActionEnum 378 | 4, // 1: user.Action.timestamp:type_name -> google.protobuf.Timestamp 379 | 2, // 2: user.UserAction.UpdateUser:input_type -> user.User 380 | 1, // 3: user.UserAction.GetUserInfo:input_type -> user.UserIdentifier 381 | 1, // 4: user.UserAction.DeleteUser:input_type -> user.UserIdentifier 382 | 3, // 5: user.UserAction.SendUserAction:input_type -> user.Action 383 | 5, // 6: user.UserAction.UpdateUser:output_type -> google.protobuf.Empty 384 | 2, // 7: user.UserAction.GetUserInfo:output_type -> user.User 385 | 5, // 8: user.UserAction.DeleteUser:output_type -> google.protobuf.Empty 386 | 5, // 9: user.UserAction.SendUserAction:output_type -> google.protobuf.Empty 387 | 6, // [6:10] is the sub-list for method output_type 388 | 2, // [2:6] is the sub-list for method input_type 389 | 2, // [2:2] is the sub-list for extension type_name 390 | 2, // [2:2] is the sub-list for extension extendee 391 | 0, // [0:2] is the sub-list for field type_name 392 | } 393 | 394 | func init() { file_proto_user_proto_init() } 395 | func file_proto_user_proto_init() { 396 | if File_proto_user_proto != nil { 397 | return 398 | } 399 | if !protoimpl.UnsafeEnabled { 400 | file_proto_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 401 | switch v := v.(*UserIdentifier); i { 402 | case 0: 403 | return &v.state 404 | case 1: 405 | return &v.sizeCache 406 | case 2: 407 | return &v.unknownFields 408 | default: 409 | return nil 410 | } 411 | } 412 | file_proto_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 413 | switch v := v.(*User); i { 414 | case 0: 415 | return &v.state 416 | case 1: 417 | return &v.sizeCache 418 | case 2: 419 | return &v.unknownFields 420 | default: 421 | return nil 422 | } 423 | } 424 | file_proto_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 425 | switch v := v.(*Action); i { 426 | case 0: 427 | return &v.state 428 | case 1: 429 | return &v.sizeCache 430 | case 2: 431 | return &v.unknownFields 432 | default: 433 | return nil 434 | } 435 | } 436 | } 437 | type x struct{} 438 | out := protoimpl.TypeBuilder{ 439 | File: protoimpl.DescBuilder{ 440 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 441 | RawDescriptor: file_proto_user_proto_rawDesc, 442 | NumEnums: 1, 443 | NumMessages: 3, 444 | NumExtensions: 0, 445 | NumServices: 1, 446 | }, 447 | GoTypes: file_proto_user_proto_goTypes, 448 | DependencyIndexes: file_proto_user_proto_depIdxs, 449 | EnumInfos: file_proto_user_proto_enumTypes, 450 | MessageInfos: file_proto_user_proto_msgTypes, 451 | }.Build() 452 | File_proto_user_proto = out.File 453 | file_proto_user_proto_rawDesc = nil 454 | file_proto_user_proto_goTypes = nil 455 | file_proto_user_proto_depIdxs = nil 456 | } 457 | -------------------------------------------------------------------------------- /grpc-gateway-demo/gen/proto/user.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.27.1 4 | // protoc (unknown) 5 | // source: proto/user.proto 6 | 7 | package _go 8 | 9 | import ( 10 | _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" 11 | _ "google.golang.org/genproto/googleapis/api/annotations" 12 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 13 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 14 | emptypb "google.golang.org/protobuf/types/known/emptypb" 15 | timestamppb "google.golang.org/protobuf/types/known/timestamppb" 16 | reflect "reflect" 17 | sync "sync" 18 | ) 19 | 20 | const ( 21 | // Verify that this generated code is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 23 | // Verify that runtime/protoimpl is sufficiently up-to-date. 24 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 25 | ) 26 | 27 | type ActionEnum int32 28 | 29 | const ( 30 | ActionEnum_DEFAULT ActionEnum = 0 31 | ActionEnum_LOGIN ActionEnum = 1 32 | ActionEnum_LOGOUT ActionEnum = 2 33 | ActionEnum_PURCHASE ActionEnum = 3 34 | ActionEnum_RETURN ActionEnum = 4 35 | ActionEnum_ADD_TO_CART ActionEnum = 5 36 | ActionEnum_REMOVE_FROM_CART ActionEnum = 6 37 | ActionEnum_VIEW_ITEM ActionEnum = 7 38 | ActionEnum_VIEW_CART ActionEnum = 8 39 | ActionEnum_VIEW_PURCHASE_HISTORY ActionEnum = 9 40 | ) 41 | 42 | // Enum value maps for ActionEnum. 43 | var ( 44 | ActionEnum_name = map[int32]string{ 45 | 0: "DEFAULT", 46 | 1: "LOGIN", 47 | 2: "LOGOUT", 48 | 3: "PURCHASE", 49 | 4: "RETURN", 50 | 5: "ADD_TO_CART", 51 | 6: "REMOVE_FROM_CART", 52 | 7: "VIEW_ITEM", 53 | 8: "VIEW_CART", 54 | 9: "VIEW_PURCHASE_HISTORY", 55 | } 56 | ActionEnum_value = map[string]int32{ 57 | "DEFAULT": 0, 58 | "LOGIN": 1, 59 | "LOGOUT": 2, 60 | "PURCHASE": 3, 61 | "RETURN": 4, 62 | "ADD_TO_CART": 5, 63 | "REMOVE_FROM_CART": 6, 64 | "VIEW_ITEM": 7, 65 | "VIEW_CART": 8, 66 | "VIEW_PURCHASE_HISTORY": 9, 67 | } 68 | ) 69 | 70 | func (x ActionEnum) Enum() *ActionEnum { 71 | p := new(ActionEnum) 72 | *p = x 73 | return p 74 | } 75 | 76 | func (x ActionEnum) String() string { 77 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 78 | } 79 | 80 | func (ActionEnum) Descriptor() protoreflect.EnumDescriptor { 81 | return file_proto_user_proto_enumTypes[0].Descriptor() 82 | } 83 | 84 | func (ActionEnum) Type() protoreflect.EnumType { 85 | return &file_proto_user_proto_enumTypes[0] 86 | } 87 | 88 | func (x ActionEnum) Number() protoreflect.EnumNumber { 89 | return protoreflect.EnumNumber(x) 90 | } 91 | 92 | // Deprecated: Use ActionEnum.Descriptor instead. 93 | func (ActionEnum) EnumDescriptor() ([]byte, []int) { 94 | return file_proto_user_proto_rawDescGZIP(), []int{0} 95 | } 96 | 97 | type UserIdentifier struct { 98 | state protoimpl.MessageState 99 | sizeCache protoimpl.SizeCache 100 | unknownFields protoimpl.UnknownFields 101 | 102 | UserId int32 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` 103 | } 104 | 105 | func (x *UserIdentifier) Reset() { 106 | *x = UserIdentifier{} 107 | if protoimpl.UnsafeEnabled { 108 | mi := &file_proto_user_proto_msgTypes[0] 109 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 110 | ms.StoreMessageInfo(mi) 111 | } 112 | } 113 | 114 | func (x *UserIdentifier) String() string { 115 | return protoimpl.X.MessageStringOf(x) 116 | } 117 | 118 | func (*UserIdentifier) ProtoMessage() {} 119 | 120 | func (x *UserIdentifier) ProtoReflect() protoreflect.Message { 121 | mi := &file_proto_user_proto_msgTypes[0] 122 | if protoimpl.UnsafeEnabled && x != nil { 123 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 124 | if ms.LoadMessageInfo() == nil { 125 | ms.StoreMessageInfo(mi) 126 | } 127 | return ms 128 | } 129 | return mi.MessageOf(x) 130 | } 131 | 132 | // Deprecated: Use UserIdentifier.ProtoReflect.Descriptor instead. 133 | func (*UserIdentifier) Descriptor() ([]byte, []int) { 134 | return file_proto_user_proto_rawDescGZIP(), []int{0} 135 | } 136 | 137 | func (x *UserIdentifier) GetUserId() int32 { 138 | if x != nil { 139 | return x.UserId 140 | } 141 | return 0 142 | } 143 | 144 | type User struct { 145 | state protoimpl.MessageState 146 | sizeCache protoimpl.SizeCache 147 | unknownFields protoimpl.UnknownFields 148 | 149 | Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 150 | Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` 151 | Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"` 152 | Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"` 153 | } 154 | 155 | func (x *User) Reset() { 156 | *x = User{} 157 | if protoimpl.UnsafeEnabled { 158 | mi := &file_proto_user_proto_msgTypes[1] 159 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 160 | ms.StoreMessageInfo(mi) 161 | } 162 | } 163 | 164 | func (x *User) String() string { 165 | return protoimpl.X.MessageStringOf(x) 166 | } 167 | 168 | func (*User) ProtoMessage() {} 169 | 170 | func (x *User) ProtoReflect() protoreflect.Message { 171 | mi := &file_proto_user_proto_msgTypes[1] 172 | if protoimpl.UnsafeEnabled && x != nil { 173 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 174 | if ms.LoadMessageInfo() == nil { 175 | ms.StoreMessageInfo(mi) 176 | } 177 | return ms 178 | } 179 | return mi.MessageOf(x) 180 | } 181 | 182 | // Deprecated: Use User.ProtoReflect.Descriptor instead. 183 | func (*User) Descriptor() ([]byte, []int) { 184 | return file_proto_user_proto_rawDescGZIP(), []int{1} 185 | } 186 | 187 | func (x *User) GetId() int32 { 188 | if x != nil { 189 | return x.Id 190 | } 191 | return 0 192 | } 193 | 194 | func (x *User) GetName() string { 195 | if x != nil { 196 | return x.Name 197 | } 198 | return "" 199 | } 200 | 201 | func (x *User) GetEmail() string { 202 | if x != nil { 203 | return x.Email 204 | } 205 | return "" 206 | } 207 | 208 | func (x *User) GetPassword() string { 209 | if x != nil { 210 | return x.Password 211 | } 212 | return "" 213 | } 214 | 215 | type Action struct { 216 | state protoimpl.MessageState 217 | sizeCache protoimpl.SizeCache 218 | unknownFields protoimpl.UnknownFields 219 | 220 | UserId int32 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` 221 | Action ActionEnum `protobuf:"varint,2,opt,name=action,proto3,enum=user.ActionEnum" json:"action,omitempty"` 222 | Success bool `protobuf:"varint,3,opt,name=success,proto3" json:"success,omitempty"` 223 | Error string `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"` 224 | Timestamp *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` 225 | } 226 | 227 | func (x *Action) Reset() { 228 | *x = Action{} 229 | if protoimpl.UnsafeEnabled { 230 | mi := &file_proto_user_proto_msgTypes[2] 231 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 232 | ms.StoreMessageInfo(mi) 233 | } 234 | } 235 | 236 | func (x *Action) String() string { 237 | return protoimpl.X.MessageStringOf(x) 238 | } 239 | 240 | func (*Action) ProtoMessage() {} 241 | 242 | func (x *Action) ProtoReflect() protoreflect.Message { 243 | mi := &file_proto_user_proto_msgTypes[2] 244 | if protoimpl.UnsafeEnabled && x != nil { 245 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 246 | if ms.LoadMessageInfo() == nil { 247 | ms.StoreMessageInfo(mi) 248 | } 249 | return ms 250 | } 251 | return mi.MessageOf(x) 252 | } 253 | 254 | // Deprecated: Use Action.ProtoReflect.Descriptor instead. 255 | func (*Action) Descriptor() ([]byte, []int) { 256 | return file_proto_user_proto_rawDescGZIP(), []int{2} 257 | } 258 | 259 | func (x *Action) GetUserId() int32 { 260 | if x != nil { 261 | return x.UserId 262 | } 263 | return 0 264 | } 265 | 266 | func (x *Action) GetAction() ActionEnum { 267 | if x != nil { 268 | return x.Action 269 | } 270 | return ActionEnum_DEFAULT 271 | } 272 | 273 | func (x *Action) GetSuccess() bool { 274 | if x != nil { 275 | return x.Success 276 | } 277 | return false 278 | } 279 | 280 | func (x *Action) GetError() string { 281 | if x != nil { 282 | return x.Error 283 | } 284 | return "" 285 | } 286 | 287 | func (x *Action) GetTimestamp() *timestamppb.Timestamp { 288 | if x != nil { 289 | return x.Timestamp 290 | } 291 | return nil 292 | } 293 | 294 | var File_proto_user_proto protoreflect.FileDescriptor 295 | 296 | var file_proto_user_proto_rawDesc = []byte{ 297 | 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 298 | 0x74, 0x6f, 0x12, 0x04, 0x75, 0x73, 0x65, 0x72, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 299 | 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 300 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 301 | 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 302 | 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 303 | 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 304 | 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 305 | 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 306 | 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 307 | 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x29, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 308 | 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 309 | 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 310 | 0x5c, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 311 | 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 312 | 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 313 | 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 314 | 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 315 | 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0xb5, 0x01, 316 | 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 317 | 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 318 | 0x64, 0x12, 0x28, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 319 | 0x0e, 0x32, 0x10, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 320 | 0x6e, 0x75, 0x6d, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 321 | 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 322 | 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 323 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x38, 0x0a, 0x09, 0x74, 324 | 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 325 | 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 326 | 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 327 | 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2a, 0xaa, 0x01, 0x0a, 0x0a, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 328 | 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 329 | 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x4f, 0x47, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 330 | 0x4c, 0x4f, 0x47, 0x4f, 0x55, 0x54, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x55, 0x52, 0x43, 331 | 0x48, 0x41, 0x53, 0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x54, 0x55, 0x52, 0x4e, 332 | 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x44, 0x44, 0x5f, 0x54, 0x4f, 0x5f, 0x43, 0x41, 0x52, 333 | 0x54, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x46, 0x52, 334 | 0x4f, 0x4d, 0x5f, 0x43, 0x41, 0x52, 0x54, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x56, 0x49, 0x45, 335 | 0x57, 0x5f, 0x49, 0x54, 0x45, 0x4d, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x56, 0x49, 0x45, 0x57, 336 | 0x5f, 0x43, 0x41, 0x52, 0x54, 0x10, 0x08, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x49, 0x45, 0x57, 0x5f, 337 | 0x50, 0x55, 0x52, 0x43, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x52, 0x59, 338 | 0x10, 0x09, 0x32, 0xe8, 0x02, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 339 | 0x6e, 0x12, 0x4e, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 340 | 0x0a, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 341 | 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 342 | 0x70, 0x74, 0x79, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x3a, 0x01, 0x2a, 0x22, 0x11, 343 | 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x7b, 0x69, 0x64, 344 | 0x7d, 0x12, 0x50, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 345 | 0x12, 0x14, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 346 | 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0x0a, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 347 | 0x65, 0x72, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x75, 0x73, 0x65, 348 | 0x72, 0x2f, 0x67, 0x65, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x5f, 349 | 0x69, 0x64, 0x7d, 0x12, 0x5d, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 350 | 0x72, 0x12, 0x14, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 351 | 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 352 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 353 | 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x75, 0x73, 0x65, 354 | 0x72, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 355 | 0x64, 0x7d, 0x12, 0x59, 0x0a, 0x0e, 0x53, 0x65, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 356 | 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0c, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x41, 0x63, 0x74, 0x69, 357 | 0x6f, 0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 358 | 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 359 | 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 360 | 0x65, 0x6e, 0x64, 0x2f, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x7d, 0x42, 0x50, 0x5a, 361 | 0x4e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x6f, 0x79, 0x70, 362 | 0x65, 0x74, 0x65, 0x2f, 0x47, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x74, 363 | 0x6f, 0x6f, 0x6c, 0x73, 0x5f, 0x65, 0x78, 0x65, 0x72, 0x63, 0x69, 0x73, 0x65, 0x73, 0x2f, 0x65, 364 | 0x78, 0x2d, 0x34, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 365 | 0x74, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x62, 366 | 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 367 | } 368 | 369 | var ( 370 | file_proto_user_proto_rawDescOnce sync.Once 371 | file_proto_user_proto_rawDescData = file_proto_user_proto_rawDesc 372 | ) 373 | 374 | func file_proto_user_proto_rawDescGZIP() []byte { 375 | file_proto_user_proto_rawDescOnce.Do(func() { 376 | file_proto_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_user_proto_rawDescData) 377 | }) 378 | return file_proto_user_proto_rawDescData 379 | } 380 | 381 | var file_proto_user_proto_enumTypes = make([]protoimpl.EnumInfo, 1) 382 | var file_proto_user_proto_msgTypes = make([]protoimpl.MessageInfo, 3) 383 | var file_proto_user_proto_goTypes = []interface{}{ 384 | (ActionEnum)(0), // 0: user.ActionEnum 385 | (*UserIdentifier)(nil), // 1: user.UserIdentifier 386 | (*User)(nil), // 2: user.User 387 | (*Action)(nil), // 3: user.Action 388 | (*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp 389 | (*emptypb.Empty)(nil), // 5: google.protobuf.Empty 390 | } 391 | var file_proto_user_proto_depIdxs = []int32{ 392 | 0, // 0: user.Action.action:type_name -> user.ActionEnum 393 | 4, // 1: user.Action.timestamp:type_name -> google.protobuf.Timestamp 394 | 2, // 2: user.UserAction.UpdateUser:input_type -> user.User 395 | 1, // 3: user.UserAction.GetUserInfo:input_type -> user.UserIdentifier 396 | 1, // 4: user.UserAction.DeleteUser:input_type -> user.UserIdentifier 397 | 3, // 5: user.UserAction.SendUserAction:input_type -> user.Action 398 | 5, // 6: user.UserAction.UpdateUser:output_type -> google.protobuf.Empty 399 | 2, // 7: user.UserAction.GetUserInfo:output_type -> user.User 400 | 5, // 8: user.UserAction.DeleteUser:output_type -> google.protobuf.Empty 401 | 5, // 9: user.UserAction.SendUserAction:output_type -> google.protobuf.Empty 402 | 6, // [6:10] is the sub-list for method output_type 403 | 2, // [2:6] is the sub-list for method input_type 404 | 2, // [2:2] is the sub-list for extension type_name 405 | 2, // [2:2] is the sub-list for extension extendee 406 | 0, // [0:2] is the sub-list for field type_name 407 | } 408 | 409 | func init() { file_proto_user_proto_init() } 410 | func file_proto_user_proto_init() { 411 | if File_proto_user_proto != nil { 412 | return 413 | } 414 | if !protoimpl.UnsafeEnabled { 415 | file_proto_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 416 | switch v := v.(*UserIdentifier); i { 417 | case 0: 418 | return &v.state 419 | case 1: 420 | return &v.sizeCache 421 | case 2: 422 | return &v.unknownFields 423 | default: 424 | return nil 425 | } 426 | } 427 | file_proto_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 428 | switch v := v.(*User); i { 429 | case 0: 430 | return &v.state 431 | case 1: 432 | return &v.sizeCache 433 | case 2: 434 | return &v.unknownFields 435 | default: 436 | return nil 437 | } 438 | } 439 | file_proto_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 440 | switch v := v.(*Action); i { 441 | case 0: 442 | return &v.state 443 | case 1: 444 | return &v.sizeCache 445 | case 2: 446 | return &v.unknownFields 447 | default: 448 | return nil 449 | } 450 | } 451 | } 452 | type x struct{} 453 | out := protoimpl.TypeBuilder{ 454 | File: protoimpl.DescBuilder{ 455 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 456 | RawDescriptor: file_proto_user_proto_rawDesc, 457 | NumEnums: 1, 458 | NumMessages: 3, 459 | NumExtensions: 0, 460 | NumServices: 1, 461 | }, 462 | GoTypes: file_proto_user_proto_goTypes, 463 | DependencyIndexes: file_proto_user_proto_depIdxs, 464 | EnumInfos: file_proto_user_proto_enumTypes, 465 | MessageInfos: file_proto_user_proto_msgTypes, 466 | }.Build() 467 | File_proto_user_proto = out.File 468 | file_proto_user_proto_rawDesc = nil 469 | file_proto_user_proto_goTypes = nil 470 | file_proto_user_proto_depIdxs = nil 471 | } 472 | -------------------------------------------------------------------------------- /grpc-gateway-demo/gen/proto/user.pb.gw.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. 2 | // source: proto/user.proto 3 | 4 | /* 5 | Package _go is a reverse proxy. 6 | 7 | It translates gRPC into RESTful JSON APIs. 8 | */ 9 | package _go 10 | 11 | import ( 12 | "context" 13 | "io" 14 | "net/http" 15 | 16 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 17 | "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" 18 | "google.golang.org/grpc" 19 | "google.golang.org/grpc/codes" 20 | "google.golang.org/grpc/grpclog" 21 | "google.golang.org/grpc/metadata" 22 | "google.golang.org/grpc/status" 23 | "google.golang.org/protobuf/proto" 24 | ) 25 | 26 | // Suppress "imported and not used" errors 27 | var _ codes.Code 28 | var _ io.Reader 29 | var _ status.Status 30 | var _ = runtime.String 31 | var _ = utilities.NewDoubleArray 32 | var _ = metadata.Join 33 | 34 | func request_UserAction_UpdateUser_0(ctx context.Context, marshaler runtime.Marshaler, client UserActionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 35 | var protoReq User 36 | var metadata runtime.ServerMetadata 37 | 38 | newReader, berr := utilities.IOReaderFactory(req.Body) 39 | if berr != nil { 40 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) 41 | } 42 | if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { 43 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 44 | } 45 | 46 | var ( 47 | val string 48 | ok bool 49 | err error 50 | _ = err 51 | ) 52 | 53 | val, ok = pathParams["id"] 54 | if !ok { 55 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") 56 | } 57 | 58 | protoReq.Id, err = runtime.Int32(val) 59 | if err != nil { 60 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) 61 | } 62 | 63 | msg, err := client.UpdateUser(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 64 | return msg, metadata, err 65 | 66 | } 67 | 68 | func local_request_UserAction_UpdateUser_0(ctx context.Context, marshaler runtime.Marshaler, server UserActionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 69 | var protoReq User 70 | var metadata runtime.ServerMetadata 71 | 72 | newReader, berr := utilities.IOReaderFactory(req.Body) 73 | if berr != nil { 74 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) 75 | } 76 | if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { 77 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 78 | } 79 | 80 | var ( 81 | val string 82 | ok bool 83 | err error 84 | _ = err 85 | ) 86 | 87 | val, ok = pathParams["id"] 88 | if !ok { 89 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") 90 | } 91 | 92 | protoReq.Id, err = runtime.Int32(val) 93 | if err != nil { 94 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) 95 | } 96 | 97 | msg, err := server.UpdateUser(ctx, &protoReq) 98 | return msg, metadata, err 99 | 100 | } 101 | 102 | func request_UserAction_GetUserInfo_0(ctx context.Context, marshaler runtime.Marshaler, client UserActionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 103 | var protoReq UserIdentifier 104 | var metadata runtime.ServerMetadata 105 | 106 | var ( 107 | val string 108 | ok bool 109 | err error 110 | _ = err 111 | ) 112 | 113 | val, ok = pathParams["user_id"] 114 | if !ok { 115 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "user_id") 116 | } 117 | 118 | protoReq.UserId, err = runtime.Int32(val) 119 | if err != nil { 120 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "user_id", err) 121 | } 122 | 123 | msg, err := client.GetUserInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 124 | return msg, metadata, err 125 | 126 | } 127 | 128 | func local_request_UserAction_GetUserInfo_0(ctx context.Context, marshaler runtime.Marshaler, server UserActionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 129 | var protoReq UserIdentifier 130 | var metadata runtime.ServerMetadata 131 | 132 | var ( 133 | val string 134 | ok bool 135 | err error 136 | _ = err 137 | ) 138 | 139 | val, ok = pathParams["user_id"] 140 | if !ok { 141 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "user_id") 142 | } 143 | 144 | protoReq.UserId, err = runtime.Int32(val) 145 | if err != nil { 146 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "user_id", err) 147 | } 148 | 149 | msg, err := server.GetUserInfo(ctx, &protoReq) 150 | return msg, metadata, err 151 | 152 | } 153 | 154 | func request_UserAction_DeleteUser_0(ctx context.Context, marshaler runtime.Marshaler, client UserActionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 155 | var protoReq UserIdentifier 156 | var metadata runtime.ServerMetadata 157 | 158 | newReader, berr := utilities.IOReaderFactory(req.Body) 159 | if berr != nil { 160 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) 161 | } 162 | if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { 163 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 164 | } 165 | 166 | var ( 167 | val string 168 | ok bool 169 | err error 170 | _ = err 171 | ) 172 | 173 | val, ok = pathParams["user_id"] 174 | if !ok { 175 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "user_id") 176 | } 177 | 178 | protoReq.UserId, err = runtime.Int32(val) 179 | if err != nil { 180 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "user_id", err) 181 | } 182 | 183 | msg, err := client.DeleteUser(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 184 | return msg, metadata, err 185 | 186 | } 187 | 188 | func local_request_UserAction_DeleteUser_0(ctx context.Context, marshaler runtime.Marshaler, server UserActionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 189 | var protoReq UserIdentifier 190 | var metadata runtime.ServerMetadata 191 | 192 | newReader, berr := utilities.IOReaderFactory(req.Body) 193 | if berr != nil { 194 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) 195 | } 196 | if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { 197 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 198 | } 199 | 200 | var ( 201 | val string 202 | ok bool 203 | err error 204 | _ = err 205 | ) 206 | 207 | val, ok = pathParams["user_id"] 208 | if !ok { 209 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "user_id") 210 | } 211 | 212 | protoReq.UserId, err = runtime.Int32(val) 213 | if err != nil { 214 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "user_id", err) 215 | } 216 | 217 | msg, err := server.DeleteUser(ctx, &protoReq) 218 | return msg, metadata, err 219 | 220 | } 221 | 222 | func request_UserAction_SendUserAction_0(ctx context.Context, marshaler runtime.Marshaler, client UserActionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 223 | var protoReq Action 224 | var metadata runtime.ServerMetadata 225 | 226 | newReader, berr := utilities.IOReaderFactory(req.Body) 227 | if berr != nil { 228 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) 229 | } 230 | if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { 231 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 232 | } 233 | 234 | var ( 235 | val string 236 | ok bool 237 | err error 238 | _ = err 239 | ) 240 | 241 | val, ok = pathParams["user_id"] 242 | if !ok { 243 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "user_id") 244 | } 245 | 246 | protoReq.UserId, err = runtime.Int32(val) 247 | if err != nil { 248 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "user_id", err) 249 | } 250 | 251 | msg, err := client.SendUserAction(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 252 | return msg, metadata, err 253 | 254 | } 255 | 256 | func local_request_UserAction_SendUserAction_0(ctx context.Context, marshaler runtime.Marshaler, server UserActionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 257 | var protoReq Action 258 | var metadata runtime.ServerMetadata 259 | 260 | newReader, berr := utilities.IOReaderFactory(req.Body) 261 | if berr != nil { 262 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) 263 | } 264 | if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { 265 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 266 | } 267 | 268 | var ( 269 | val string 270 | ok bool 271 | err error 272 | _ = err 273 | ) 274 | 275 | val, ok = pathParams["user_id"] 276 | if !ok { 277 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "user_id") 278 | } 279 | 280 | protoReq.UserId, err = runtime.Int32(val) 281 | if err != nil { 282 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "user_id", err) 283 | } 284 | 285 | msg, err := server.SendUserAction(ctx, &protoReq) 286 | return msg, metadata, err 287 | 288 | } 289 | 290 | // RegisterUserActionHandlerServer registers the http handlers for service UserAction to "mux". 291 | // UnaryRPC :call UserActionServer directly. 292 | // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. 293 | // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterUserActionHandlerFromEndpoint instead. 294 | func RegisterUserActionHandlerServer(ctx context.Context, mux *runtime.ServeMux, server UserActionServer) error { 295 | 296 | mux.Handle("POST", pattern_UserAction_UpdateUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 297 | ctx, cancel := context.WithCancel(req.Context()) 298 | defer cancel() 299 | var stream runtime.ServerTransportStream 300 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 301 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 302 | rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/user.UserAction/UpdateUser", runtime.WithHTTPPathPattern("/user/update/{id}")) 303 | if err != nil { 304 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 305 | return 306 | } 307 | resp, md, err := local_request_UserAction_UpdateUser_0(rctx, inboundMarshaler, server, req, pathParams) 308 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 309 | ctx = runtime.NewServerMetadataContext(ctx, md) 310 | if err != nil { 311 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 312 | return 313 | } 314 | 315 | forward_UserAction_UpdateUser_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 316 | 317 | }) 318 | 319 | mux.Handle("GET", pattern_UserAction_GetUserInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 320 | ctx, cancel := context.WithCancel(req.Context()) 321 | defer cancel() 322 | var stream runtime.ServerTransportStream 323 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 324 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 325 | rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/user.UserAction/GetUserInfo", runtime.WithHTTPPathPattern("/user/getinfo/{user_id}")) 326 | if err != nil { 327 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 328 | return 329 | } 330 | resp, md, err := local_request_UserAction_GetUserInfo_0(rctx, inboundMarshaler, server, req, pathParams) 331 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 332 | ctx = runtime.NewServerMetadataContext(ctx, md) 333 | if err != nil { 334 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 335 | return 336 | } 337 | 338 | forward_UserAction_GetUserInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 339 | 340 | }) 341 | 342 | mux.Handle("POST", pattern_UserAction_DeleteUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 343 | ctx, cancel := context.WithCancel(req.Context()) 344 | defer cancel() 345 | var stream runtime.ServerTransportStream 346 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 347 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 348 | rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/user.UserAction/DeleteUser", runtime.WithHTTPPathPattern("/user/delete/{user_id}")) 349 | if err != nil { 350 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 351 | return 352 | } 353 | resp, md, err := local_request_UserAction_DeleteUser_0(rctx, inboundMarshaler, server, req, pathParams) 354 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 355 | ctx = runtime.NewServerMetadataContext(ctx, md) 356 | if err != nil { 357 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 358 | return 359 | } 360 | 361 | forward_UserAction_DeleteUser_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 362 | 363 | }) 364 | 365 | mux.Handle("POST", pattern_UserAction_SendUserAction_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 366 | ctx, cancel := context.WithCancel(req.Context()) 367 | defer cancel() 368 | var stream runtime.ServerTransportStream 369 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 370 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 371 | rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/user.UserAction/SendUserAction", runtime.WithHTTPPathPattern("/action/send/{user_id}")) 372 | if err != nil { 373 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 374 | return 375 | } 376 | resp, md, err := local_request_UserAction_SendUserAction_0(rctx, inboundMarshaler, server, req, pathParams) 377 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 378 | ctx = runtime.NewServerMetadataContext(ctx, md) 379 | if err != nil { 380 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 381 | return 382 | } 383 | 384 | forward_UserAction_SendUserAction_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 385 | 386 | }) 387 | 388 | return nil 389 | } 390 | 391 | // RegisterUserActionHandlerFromEndpoint is same as RegisterUserActionHandler but 392 | // automatically dials to "endpoint" and closes the connection when "ctx" gets done. 393 | func RegisterUserActionHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { 394 | conn, err := grpc.Dial(endpoint, opts...) 395 | if err != nil { 396 | return err 397 | } 398 | defer func() { 399 | if err != nil { 400 | if cerr := conn.Close(); cerr != nil { 401 | grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) 402 | } 403 | return 404 | } 405 | go func() { 406 | <-ctx.Done() 407 | if cerr := conn.Close(); cerr != nil { 408 | grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) 409 | } 410 | }() 411 | }() 412 | 413 | return RegisterUserActionHandler(ctx, mux, conn) 414 | } 415 | 416 | // RegisterUserActionHandler registers the http handlers for service UserAction to "mux". 417 | // The handlers forward requests to the grpc endpoint over "conn". 418 | func RegisterUserActionHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { 419 | return RegisterUserActionHandlerClient(ctx, mux, NewUserActionClient(conn)) 420 | } 421 | 422 | // RegisterUserActionHandlerClient registers the http handlers for service UserAction 423 | // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "UserActionClient". 424 | // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "UserActionClient" 425 | // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in 426 | // "UserActionClient" to call the correct interceptors. 427 | func RegisterUserActionHandlerClient(ctx context.Context, mux *runtime.ServeMux, client UserActionClient) error { 428 | 429 | mux.Handle("POST", pattern_UserAction_UpdateUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 430 | ctx, cancel := context.WithCancel(req.Context()) 431 | defer cancel() 432 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 433 | rctx, err := runtime.AnnotateContext(ctx, mux, req, "/user.UserAction/UpdateUser", runtime.WithHTTPPathPattern("/user/update/{id}")) 434 | if err != nil { 435 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 436 | return 437 | } 438 | resp, md, err := request_UserAction_UpdateUser_0(rctx, inboundMarshaler, client, req, pathParams) 439 | ctx = runtime.NewServerMetadataContext(ctx, md) 440 | if err != nil { 441 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 442 | return 443 | } 444 | 445 | forward_UserAction_UpdateUser_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 446 | 447 | }) 448 | 449 | mux.Handle("GET", pattern_UserAction_GetUserInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 450 | ctx, cancel := context.WithCancel(req.Context()) 451 | defer cancel() 452 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 453 | rctx, err := runtime.AnnotateContext(ctx, mux, req, "/user.UserAction/GetUserInfo", runtime.WithHTTPPathPattern("/user/getinfo/{user_id}")) 454 | if err != nil { 455 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 456 | return 457 | } 458 | resp, md, err := request_UserAction_GetUserInfo_0(rctx, inboundMarshaler, client, req, pathParams) 459 | ctx = runtime.NewServerMetadataContext(ctx, md) 460 | if err != nil { 461 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 462 | return 463 | } 464 | 465 | forward_UserAction_GetUserInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 466 | 467 | }) 468 | 469 | mux.Handle("POST", pattern_UserAction_DeleteUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 470 | ctx, cancel := context.WithCancel(req.Context()) 471 | defer cancel() 472 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 473 | rctx, err := runtime.AnnotateContext(ctx, mux, req, "/user.UserAction/DeleteUser", runtime.WithHTTPPathPattern("/user/delete/{user_id}")) 474 | if err != nil { 475 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 476 | return 477 | } 478 | resp, md, err := request_UserAction_DeleteUser_0(rctx, inboundMarshaler, client, req, pathParams) 479 | ctx = runtime.NewServerMetadataContext(ctx, md) 480 | if err != nil { 481 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 482 | return 483 | } 484 | 485 | forward_UserAction_DeleteUser_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 486 | 487 | }) 488 | 489 | mux.Handle("POST", pattern_UserAction_SendUserAction_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 490 | ctx, cancel := context.WithCancel(req.Context()) 491 | defer cancel() 492 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 493 | rctx, err := runtime.AnnotateContext(ctx, mux, req, "/user.UserAction/SendUserAction", runtime.WithHTTPPathPattern("/action/send/{user_id}")) 494 | if err != nil { 495 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 496 | return 497 | } 498 | resp, md, err := request_UserAction_SendUserAction_0(rctx, inboundMarshaler, client, req, pathParams) 499 | ctx = runtime.NewServerMetadataContext(ctx, md) 500 | if err != nil { 501 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 502 | return 503 | } 504 | 505 | forward_UserAction_SendUserAction_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 506 | 507 | }) 508 | 509 | return nil 510 | } 511 | 512 | var ( 513 | pattern_UserAction_UpdateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"user", "update", "id"}, "")) 514 | 515 | pattern_UserAction_GetUserInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"user", "getinfo", "user_id"}, "")) 516 | 517 | pattern_UserAction_DeleteUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"user", "delete", "user_id"}, "")) 518 | 519 | pattern_UserAction_SendUserAction_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"action", "send", "user_id"}, "")) 520 | ) 521 | 522 | var ( 523 | forward_UserAction_UpdateUser_0 = runtime.ForwardResponseMessage 524 | 525 | forward_UserAction_GetUserInfo_0 = runtime.ForwardResponseMessage 526 | 527 | forward_UserAction_DeleteUser_0 = runtime.ForwardResponseMessage 528 | 529 | forward_UserAction_SendUserAction_0 = runtime.ForwardResponseMessage 530 | ) 531 | --------------------------------------------------------------------------------