├── .gitattributes ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── example ├── main.go └── v1 │ ├── auth_type.pb.go │ ├── greeter.pb.go │ ├── greeter.proto │ ├── greeter_handler.pb.go │ └── greeter_router.pb.go ├── go.mod ├── go.sum ├── http.go ├── http_test.go ├── main.go ├── runtime ├── proto_decode.go └── well_known_types.go ├── template.go └── third_party └── google ├── api ├── annotations.proto ├── client.proto ├── field_behavior.proto ├── http.proto ├── httpbody.proto ├── resource.proto └── routing.proto └── protobuf ├── any.proto ├── api.proto ├── compiler └── plugin.proto ├── descriptor.proto ├── duration.proto ├── empty.proto ├── field_mask.proto ├── source_context.proto ├── struct.proto ├── timestamp.proto ├── type.proto └── wrappers.proto /.gitattributes: -------------------------------------------------------------------------------- 1 | Makefile linguist-detectable=false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.test 2 | .vscode/ 3 | .idea/ 4 | *.swp 5 | *.log 6 | Thumbs.db 7 | .DS_Store 8 | *.exe 9 | *.exe~ 10 | *.dll 11 | *.so 12 | *.dylib 13 | *.out 14 | *.o 15 | *.a 16 | *.so 17 | bin/ 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 go-woo 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GOHOSTOS:=$(shell go env GOHOSTOS) 2 | GOPATH:=$(shell go env GOPATH) 3 | VERSION=$(shell git describe --tags --always) 4 | 5 | ifeq ($(GOHOSTOS), windows) 6 | #the `find.exe` is different from `find` in bash/shell. 7 | #to see https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/find. 8 | #changed to use git-bash.exe to run find cli or other cli friendly, caused of every developer has a Git. 9 | Git_Bash= $(subst cmd\,bin\bash.exe,$(dir $(shell where git))) 10 | INTERNAL_PROTO_FILES=$(shell $(Git_Bash) -c "find ./example/v1 -name *.proto") 11 | API_PROTO_FILES=$(shell $(Git_Bash) -c "find ./example/v1 -name *.proto") 12 | else 13 | INTERNAL_PROTO_FILES=$(shell find ./example/v1 -name *.proto) 14 | API_PROTO_FILES=$(shell find ./example/v1 -name *.proto) 15 | endif 16 | 17 | .PHONY: init 18 | # init tools-chain 19 | init: 20 | go install google.golang.org/protobuf/cmd/protoc-gen-go@latest 21 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest 22 | go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest 23 | go install github.com/go-woo/protoc-gen-echo@latest 24 | 25 | .PHONY: api 26 | # generate api proto 27 | api: 28 | protoc --proto_path=. \ 29 | --proto_path=./third_party \ 30 | --go_out=paths=source_relative:. \ 31 | --echo_out=paths=source_relative:. \ 32 | $(API_PROTO_FILES) 33 | 34 | .PHONY: example 35 | # example 36 | example: 37 | make init; 38 | make api; 39 | 40 | .PHONY: all 41 | # generate all 42 | all: 43 | go install . 44 | make api; 45 | 46 | .PHONY: clear 47 | # clear 48 | clear: 49 | rm ./example/v1/*.pb.go 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## What is protoc-gen-echo? 2 | `protoc-gen-echo` is a protoc plug-in that generates [Echo](https://github.com/labstack/echo) server code 3 | from proto file. 4 | 5 | If you want to create a [Echo](https://github.com/labstack/echo)'s http api 6 | `/helloworld/:name/hi/:nice`, you just need to add rpc in a proto file, and generate it. 7 | 8 | `/helloworld/:name/hi/:nice` mapping http api will be generated by `protoc-gen-echo`. 9 | 10 | `protoc-gen-echo` can generate complete backend all code combination with [protoc-gen-ent](https://github.com/go-woo/protoc-gen-ent). 11 | 12 | ** About ent you can find more help from [ent](https://github.com/ent/ent). 13 | ## Quick start 14 | ### Step 0: Pre-installation on ubuntu 15 | ``` 16 | sudo apt install protobuf-compiler make 17 | ``` 18 | ### Step 1: Edit `./example/v1/greeter.proto` 19 | ``` 20 | service Greeter { 21 | // Sends a greeting 22 | rpc SayHello (HelloRequest) returns (HelloReply) { 23 | option (google.api.http) = { 24 | get: "/helloworld/{name}/hi/{nice}" 25 | }; 26 | } 27 | //... 28 | } 29 | //... 30 | ``` 31 | 32 | ### Step 2: Generate 33 | 34 | You can generate code used by `make`: 35 | ``` 36 | make example 37 | ``` 38 | Or you can generate code used by below too: 39 | ``` 40 | go install google.golang.org/protobuf/cmd/protoc-gen-go@latest 41 | 42 | go install github.com/go-woo/protoc-gen-echo@latest 43 | 44 | protoc --proto_path=. \ 45 | --proto_path=./third_party \ 46 | --go_out=paths=source_relative:. \ 47 | --echo_out=paths=source_relative:. \ 48 | ./example/v1/greeter.proto 49 | ``` 50 | The `protoc-gen-echo` generated 2 files:`greeter_router.pb.go` and `greeter_handler.pb.go`. 51 | 52 | The `greeter.pb.go` was generated by [protoc-gen-go](https://github.com/golang/protobuf/tree/master/protoc-gen-go) 53 | 54 | More help can be found in [protoc](https://github.com/protocolbuffers/protobuf). 55 | 56 | Your business logic stubs has been generated in `your_xxxx_handler.pb.go`, 57 | You can edit business logic in stubs. 58 | ``` 59 | func $(YourService)$(RpcName)BusinessHandler(payload *YourRequest) (YourReply, error) { 60 | // Here can put your business logic, can use ORM:github.com/go-woo/protoc-gen-ent 61 | return YourReply{}, nil 62 | } 63 | ``` 64 | All handlers typo can be found in `your_xxxx_router.pb.go`. 65 | 66 | ### Step 3: Write example business logic 67 | 68 | For this example, in `greeter_router.pb.go`. 69 | You can find generated echo's handler `_Greeter_SayHello0_HTTP_Handler`. 70 | ``` 71 | func RegisterGreeterRouter(e *echo.Echo) { 72 | e.GET("/helloworld/:name/hi/:nice", _Greeter_SayHello0_HTTP_Handler) 73 | //... 74 | } 75 | ``` 76 | In same file, you can find `_Greeter_SayHello0_HTTP_Handler`'s implement: 77 | ``` 78 | func _Greeter_SayHello0_HTTP_Handler(c echo.Context) error { 79 | var req *HelloRequest = new(HelloRequest) 80 | 81 | req.Name = c.Param(strings.ToLower("Name")) 82 | req.Nice = c.Param(strings.ToLower("Nice")) 83 | reply, err := GreeterSayHelloBusinessHandler(req, c) 84 | if err != nil { 85 | return err 86 | } 87 | 88 | return c.JSON(http.StatusOK, &reply) 89 | } 90 | ``` 91 | Our focus is on `GreeterSayHelloBusinessHandler(payload)`. 92 | In `greeter_handler.pb.go`, you can write business logic. 93 | ``` 94 | func GreeterSayHelloBusinessHandler(req *HelloRequest, c echo.Context) (HelloReply, error) { 95 | // Here can put your business logic,protoc-gen-ent soon coming 96 | reqJson, err := json.Marshal(req) 97 | if err != nil { 98 | return HelloReply{}, err 99 | } 100 | fmt.Printf("Got HelloRequest is: %v\n", string(reqJson)) 101 | 102 | return HelloReply{}, nil 103 | } 104 | ``` 105 | For running this example we need to write a `main.go` 106 | ``` 107 | package main 108 | 109 | import ( 110 | v1 "github.com/go-woo/protoc-gen-echo/example/v1" 111 | "github.com/labstack/echo/v4" 112 | "github.com/labstack/echo/v4/middleware" 113 | ) 114 | 115 | func main() { 116 | e := echo.New() 117 | 118 | e.Use(middleware.Logger()) 119 | e.Use(middleware.Recover()) 120 | 121 | v1.RegisterGreeterRouter(e) 122 | // you can add custom router outside protoc-gen-echo too. 123 | // MyCustomRouter(e) 124 | 125 | e.Logger.Fatal(e.Start(":1323")) 126 | } 127 | ``` 128 | More help and doc can be found on [Echo](https://github.com/labstack/echo) , 129 | include rate limited, auto update TLS cert, etc. 130 | ### Step 4: Run example 131 | ``` 132 | cd example && go run main.go 133 | ``` 134 | Open browser, URL:`http://localhost:1223/helloworld/Lok-Tar/hi/Ogar` 135 | 136 | Or shell execute 137 | ``` 138 | curl -X GET http://localhost:1323/helloworld/Lok-Tar/hi/Ogar 139 | ``` 140 | ### Step 5: Optional JWT support 141 | Service option 142 | ``` 143 | //get token URL 144 | option (google.api.default_host) = "/login"; 145 | //need auth root path, can multi path 146 | option (google.api.oauth_scopes) = 147 | "/restricted," 148 | ``` 149 | was used for JWT describer. 150 | 151 | If you want to support JWT, can add it. Else you can comment it. 152 | 153 | ## :bangbang: Special notes 154 | 155 | * Do not remove `your_xxxx_handler.pb.go`. It was generated only when the first time, and will not be generated or overwritten after that again, because the business logic code you added is already in it. 156 | 157 | * JSON format in http body. If http client request has body, header should has `Content-Type: application/json` 158 | 159 | * Validate. Single source(proto) is the most important means to ensure consistency. protobuf message filed validate can use [protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate). 160 | 161 | * `protoc-gen-echo` follow [google.api.httprule](https://cloud.google.com/service-infrastructure/docs/service-management/reference/rpc/google.api#http). 162 | 163 | * [ent](https://github.com/ent/ent) still does not support message nesting, so proto http rule body must be *. 164 | 165 | ## Generate gRPC 166 | gRPC generated by [protoc-gen-go-grpc](https://github.com/grpc/grpc-go/tree/master/cmd/protoc-gen-go-grpc) 167 | ``` 168 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest 169 | ``` 170 | Add `--go-grpc_out=paths=source_relative:. \` 171 | ``` 172 | protoc --proto_path=. \ 173 | --proto_path=./third_party \ 174 | --go_out=paths=source_relative:. \ 175 | --echo_out=paths=source_relative:. \ 176 | --go-grpc_out=paths=source_relative:. \ 177 | ./example/v1/greeter.proto 178 | ``` 179 | ## Generate Open Api Spec document 180 | OAS generated by [protoc-gen-openapi](https://github.com/google/gnostic/tree/main/cmd/protoc-gen-openapi) 181 | ``` 182 | go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest 183 | ``` 184 | Add `--openapi_out=paths=source_relative:. \` 185 | ``` 186 | protoc --proto_path=. \ 187 | --proto_path=./third_party \ 188 | --go_out=paths=source_relative:. \ 189 | --echo_out=paths=source_relative:. \ 190 | --openapi_out=paths=source_relative:. \ 191 | ./example/v1/greeter.proto 192 | ``` 193 | Generated yaml file can be browser on swagger or openapi 194 | ## Validate 195 | Fields validate generated by [protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate) 196 | ``` 197 | go install github.com/envoyproxy/protoc-gen-validate@latest 198 | ``` 199 | Add `--validate_out="lang=go:." \` 200 | ``` 201 | protoc --proto_path=. \ 202 | --proto_path=./third_party \ 203 | --go_out=paths=source_relative:. \ 204 | --echo_out=paths=source_relative:. \ 205 | --validate_out="lang=go:." \ 206 | ./example/v1/greeter.proto 207 | ``` 208 | 209 | ## Todo 210 | * Add generate jwt openapi/swagger support 211 | ``` 212 | https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication 213 | https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#securitySchemeObject 214 | https://github.com/grpc-ecosystem/grpc-gateway/blob/master/examples/internal/proto/examplepb/a_bit_of_everything.proto 215 | ``` -------------------------------------------------------------------------------- /example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | v1 "github.com/go-woo/protoc-gen-echo/example/v1" 5 | "github.com/labstack/echo/v4" 6 | "github.com/labstack/echo/v4/middleware" 7 | ) 8 | 9 | func main() { 10 | e := echo.New() 11 | 12 | e.Use(middleware.Logger()) 13 | e.Use(middleware.Recover()) 14 | 15 | v1.RegisterGreeterRouter(e) 16 | // you can add custom router outside protoc-gen-echo too. 17 | // MyCustomRouter(e) 18 | 19 | e.Logger.Fatal(e.Start(":1323")) 20 | } 21 | -------------------------------------------------------------------------------- /example/v1/auth_type.pb.go: -------------------------------------------------------------------------------- 1 | // Auth use data type. 2 | // versions: 3 | // - protoc-gen-echo v0.1.1 4 | // - protoc v3.12.4 5 | // source: example/v1/greeter.proto 6 | 7 | package v1 8 | 9 | import "github.com/golang-jwt/jwt" 10 | 11 | // jwtCustomClaims are custom claims extending default ones. 12 | // See https://github.com/golang-jwt/jwt for more examples 13 | type JwtCustomClaims struct { 14 | Name string `json:"name"` 15 | Admin bool `json:"admin"` 16 | jwt.StandardClaims 17 | } 18 | -------------------------------------------------------------------------------- /example/v1/greeter.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.1 4 | // protoc v3.12.4 5 | // source: example/v1/greeter.proto 6 | 7 | package v1 8 | 9 | import ( 10 | _ "google.golang.org/genproto/googleapis/api/annotations" 11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type Foo int32 25 | 26 | const ( 27 | Foo_DEFAULT_BAR Foo = 0 28 | Foo_BAR_BELLS Foo = 1 29 | Foo_BAR_B_CUE Foo = 2 30 | ) 31 | 32 | // Enum value maps for Foo. 33 | var ( 34 | Foo_name = map[int32]string{ 35 | 0: "DEFAULT_BAR", 36 | 1: "BAR_BELLS", 37 | 2: "BAR_B_CUE", 38 | } 39 | Foo_value = map[string]int32{ 40 | "DEFAULT_BAR": 0, 41 | "BAR_BELLS": 1, 42 | "BAR_B_CUE": 2, 43 | } 44 | ) 45 | 46 | func (x Foo) Enum() *Foo { 47 | p := new(Foo) 48 | *p = x 49 | return p 50 | } 51 | 52 | func (x Foo) String() string { 53 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 54 | } 55 | 56 | func (Foo) Descriptor() protoreflect.EnumDescriptor { 57 | return file_example_v1_greeter_proto_enumTypes[0].Descriptor() 58 | } 59 | 60 | func (Foo) Type() protoreflect.EnumType { 61 | return &file_example_v1_greeter_proto_enumTypes[0] 62 | } 63 | 64 | func (x Foo) Number() protoreflect.EnumNumber { 65 | return protoreflect.EnumNumber(x) 66 | } 67 | 68 | // Deprecated: Use Foo.Descriptor instead. 69 | func (Foo) EnumDescriptor() ([]byte, []int) { 70 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{0} 71 | } 72 | 73 | type HelloRequest_Corpus int32 74 | 75 | const ( 76 | HelloRequest_UNIVERSAL HelloRequest_Corpus = 0 77 | HelloRequest_WEB HelloRequest_Corpus = 1 78 | HelloRequest_IMAGES HelloRequest_Corpus = 2 79 | HelloRequest_LOCAL HelloRequest_Corpus = 3 80 | HelloRequest_NEWS HelloRequest_Corpus = 4 81 | HelloRequest_PRODUCTS HelloRequest_Corpus = 5 82 | HelloRequest_VIDEO HelloRequest_Corpus = 6 83 | ) 84 | 85 | // Enum value maps for HelloRequest_Corpus. 86 | var ( 87 | HelloRequest_Corpus_name = map[int32]string{ 88 | 0: "UNIVERSAL", 89 | 1: "WEB", 90 | 2: "IMAGES", 91 | 3: "LOCAL", 92 | 4: "NEWS", 93 | 5: "PRODUCTS", 94 | 6: "VIDEO", 95 | } 96 | HelloRequest_Corpus_value = map[string]int32{ 97 | "UNIVERSAL": 0, 98 | "WEB": 1, 99 | "IMAGES": 2, 100 | "LOCAL": 3, 101 | "NEWS": 4, 102 | "PRODUCTS": 5, 103 | "VIDEO": 6, 104 | } 105 | ) 106 | 107 | func (x HelloRequest_Corpus) Enum() *HelloRequest_Corpus { 108 | p := new(HelloRequest_Corpus) 109 | *p = x 110 | return p 111 | } 112 | 113 | func (x HelloRequest_Corpus) String() string { 114 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 115 | } 116 | 117 | func (HelloRequest_Corpus) Descriptor() protoreflect.EnumDescriptor { 118 | return file_example_v1_greeter_proto_enumTypes[1].Descriptor() 119 | } 120 | 121 | func (HelloRequest_Corpus) Type() protoreflect.EnumType { 122 | return &file_example_v1_greeter_proto_enumTypes[1] 123 | } 124 | 125 | func (x HelloRequest_Corpus) Number() protoreflect.EnumNumber { 126 | return protoreflect.EnumNumber(x) 127 | } 128 | 129 | // Deprecated: Use HelloRequest_Corpus.Descriptor instead. 130 | func (HelloRequest_Corpus) EnumDescriptor() ([]byte, []int) { 131 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{0, 0} 132 | } 133 | 134 | // The request message containing the user's name. 135 | type HelloRequest struct { 136 | state protoimpl.MessageState 137 | sizeCache protoimpl.SizeCache 138 | unknownFields protoimpl.UnknownFields 139 | 140 | Name int32 `protobuf:"varint,1,opt,name=name,proto3" json:"name,omitempty"` 141 | Nice string `protobuf:"bytes,2,opt,name=nice,proto3" json:"nice,omitempty"` 142 | Uid int64 `protobuf:"varint,3,opt,name=uid,proto3" json:"uid,omitempty"` 143 | Authed bool `protobuf:"varint,4,opt,name=authed,proto3" json:"authed,omitempty"` 144 | Corpus HelloRequest_Corpus `protobuf:"varint,5,opt,name=corpus,proto3,enum=v1.HelloRequest_Corpus" json:"corpus,omitempty"` 145 | } 146 | 147 | func (x *HelloRequest) Reset() { 148 | *x = HelloRequest{} 149 | if protoimpl.UnsafeEnabled { 150 | mi := &file_example_v1_greeter_proto_msgTypes[0] 151 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 152 | ms.StoreMessageInfo(mi) 153 | } 154 | } 155 | 156 | func (x *HelloRequest) String() string { 157 | return protoimpl.X.MessageStringOf(x) 158 | } 159 | 160 | func (*HelloRequest) ProtoMessage() {} 161 | 162 | func (x *HelloRequest) ProtoReflect() protoreflect.Message { 163 | mi := &file_example_v1_greeter_proto_msgTypes[0] 164 | if protoimpl.UnsafeEnabled && x != nil { 165 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 166 | if ms.LoadMessageInfo() == nil { 167 | ms.StoreMessageInfo(mi) 168 | } 169 | return ms 170 | } 171 | return mi.MessageOf(x) 172 | } 173 | 174 | // Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead. 175 | func (*HelloRequest) Descriptor() ([]byte, []int) { 176 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{0} 177 | } 178 | 179 | func (x *HelloRequest) GetName() int32 { 180 | if x != nil { 181 | return x.Name 182 | } 183 | return 0 184 | } 185 | 186 | func (x *HelloRequest) GetNice() string { 187 | if x != nil { 188 | return x.Nice 189 | } 190 | return "" 191 | } 192 | 193 | func (x *HelloRequest) GetUid() int64 { 194 | if x != nil { 195 | return x.Uid 196 | } 197 | return 0 198 | } 199 | 200 | func (x *HelloRequest) GetAuthed() bool { 201 | if x != nil { 202 | return x.Authed 203 | } 204 | return false 205 | } 206 | 207 | func (x *HelloRequest) GetCorpus() HelloRequest_Corpus { 208 | if x != nil { 209 | return x.Corpus 210 | } 211 | return HelloRequest_UNIVERSAL 212 | } 213 | 214 | // The response message containing the greetings 215 | type HelloReply struct { 216 | state protoimpl.MessageState 217 | sizeCache protoimpl.SizeCache 218 | unknownFields protoimpl.UnknownFields 219 | 220 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 221 | } 222 | 223 | func (x *HelloReply) Reset() { 224 | *x = HelloReply{} 225 | if protoimpl.UnsafeEnabled { 226 | mi := &file_example_v1_greeter_proto_msgTypes[1] 227 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 228 | ms.StoreMessageInfo(mi) 229 | } 230 | } 231 | 232 | func (x *HelloReply) String() string { 233 | return protoimpl.X.MessageStringOf(x) 234 | } 235 | 236 | func (*HelloReply) ProtoMessage() {} 237 | 238 | func (x *HelloReply) ProtoReflect() protoreflect.Message { 239 | mi := &file_example_v1_greeter_proto_msgTypes[1] 240 | if protoimpl.UnsafeEnabled && x != nil { 241 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 242 | if ms.LoadMessageInfo() == nil { 243 | ms.StoreMessageInfo(mi) 244 | } 245 | return ms 246 | } 247 | return mi.MessageOf(x) 248 | } 249 | 250 | // Deprecated: Use HelloReply.ProtoReflect.Descriptor instead. 251 | func (*HelloReply) Descriptor() ([]byte, []int) { 252 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{1} 253 | } 254 | 255 | func (x *HelloReply) GetMessage() string { 256 | if x != nil { 257 | return x.Message 258 | } 259 | return "" 260 | } 261 | 262 | // Login request must include username and password field. 263 | type CreateUserRequest struct { 264 | state protoimpl.MessageState 265 | sizeCache protoimpl.SizeCache 266 | unknownFields protoimpl.UnknownFields 267 | 268 | Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` 269 | Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` 270 | } 271 | 272 | func (x *CreateUserRequest) Reset() { 273 | *x = CreateUserRequest{} 274 | if protoimpl.UnsafeEnabled { 275 | mi := &file_example_v1_greeter_proto_msgTypes[2] 276 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 277 | ms.StoreMessageInfo(mi) 278 | } 279 | } 280 | 281 | func (x *CreateUserRequest) String() string { 282 | return protoimpl.X.MessageStringOf(x) 283 | } 284 | 285 | func (*CreateUserRequest) ProtoMessage() {} 286 | 287 | func (x *CreateUserRequest) ProtoReflect() protoreflect.Message { 288 | mi := &file_example_v1_greeter_proto_msgTypes[2] 289 | if protoimpl.UnsafeEnabled && x != nil { 290 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 291 | if ms.LoadMessageInfo() == nil { 292 | ms.StoreMessageInfo(mi) 293 | } 294 | return ms 295 | } 296 | return mi.MessageOf(x) 297 | } 298 | 299 | // Deprecated: Use CreateUserRequest.ProtoReflect.Descriptor instead. 300 | func (*CreateUserRequest) Descriptor() ([]byte, []int) { 301 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{2} 302 | } 303 | 304 | func (x *CreateUserRequest) GetUsername() string { 305 | if x != nil { 306 | return x.Username 307 | } 308 | return "" 309 | } 310 | 311 | func (x *CreateUserRequest) GetPassword() string { 312 | if x != nil { 313 | return x.Password 314 | } 315 | return "" 316 | } 317 | 318 | // Login reply must include token field. 319 | type CreateUserReply struct { 320 | state protoimpl.MessageState 321 | sizeCache protoimpl.SizeCache 322 | unknownFields protoimpl.UnknownFields 323 | 324 | Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` 325 | } 326 | 327 | func (x *CreateUserReply) Reset() { 328 | *x = CreateUserReply{} 329 | if protoimpl.UnsafeEnabled { 330 | mi := &file_example_v1_greeter_proto_msgTypes[3] 331 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 332 | ms.StoreMessageInfo(mi) 333 | } 334 | } 335 | 336 | func (x *CreateUserReply) String() string { 337 | return protoimpl.X.MessageStringOf(x) 338 | } 339 | 340 | func (*CreateUserReply) ProtoMessage() {} 341 | 342 | func (x *CreateUserReply) ProtoReflect() protoreflect.Message { 343 | mi := &file_example_v1_greeter_proto_msgTypes[3] 344 | if protoimpl.UnsafeEnabled && x != nil { 345 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 346 | if ms.LoadMessageInfo() == nil { 347 | ms.StoreMessageInfo(mi) 348 | } 349 | return ms 350 | } 351 | return mi.MessageOf(x) 352 | } 353 | 354 | // Deprecated: Use CreateUserReply.ProtoReflect.Descriptor instead. 355 | func (*CreateUserReply) Descriptor() ([]byte, []int) { 356 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{3} 357 | } 358 | 359 | func (x *CreateUserReply) GetToken() string { 360 | if x != nil { 361 | return x.Token 362 | } 363 | return "" 364 | } 365 | 366 | // The request message containing the user's name. 367 | type UpdateUserRequest struct { 368 | state protoimpl.MessageState 369 | sizeCache protoimpl.SizeCache 370 | unknownFields protoimpl.UnknownFields 371 | 372 | Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` 373 | Phone string `protobuf:"bytes,2,opt,name=phone,proto3" json:"phone,omitempty"` 374 | Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"` 375 | } 376 | 377 | func (x *UpdateUserRequest) Reset() { 378 | *x = UpdateUserRequest{} 379 | if protoimpl.UnsafeEnabled { 380 | mi := &file_example_v1_greeter_proto_msgTypes[4] 381 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 382 | ms.StoreMessageInfo(mi) 383 | } 384 | } 385 | 386 | func (x *UpdateUserRequest) String() string { 387 | return protoimpl.X.MessageStringOf(x) 388 | } 389 | 390 | func (*UpdateUserRequest) ProtoMessage() {} 391 | 392 | func (x *UpdateUserRequest) ProtoReflect() protoreflect.Message { 393 | mi := &file_example_v1_greeter_proto_msgTypes[4] 394 | if protoimpl.UnsafeEnabled && x != nil { 395 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 396 | if ms.LoadMessageInfo() == nil { 397 | ms.StoreMessageInfo(mi) 398 | } 399 | return ms 400 | } 401 | return mi.MessageOf(x) 402 | } 403 | 404 | // Deprecated: Use UpdateUserRequest.ProtoReflect.Descriptor instead. 405 | func (*UpdateUserRequest) Descriptor() ([]byte, []int) { 406 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{4} 407 | } 408 | 409 | func (x *UpdateUserRequest) GetUsername() string { 410 | if x != nil { 411 | return x.Username 412 | } 413 | return "" 414 | } 415 | 416 | func (x *UpdateUserRequest) GetPhone() string { 417 | if x != nil { 418 | return x.Phone 419 | } 420 | return "" 421 | } 422 | 423 | func (x *UpdateUserRequest) GetEmail() string { 424 | if x != nil { 425 | return x.Email 426 | } 427 | return "" 428 | } 429 | 430 | // The response message containing the greetings 431 | type UpdateUserReply struct { 432 | state protoimpl.MessageState 433 | sizeCache protoimpl.SizeCache 434 | unknownFields protoimpl.UnknownFields 435 | 436 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 437 | Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` 438 | } 439 | 440 | func (x *UpdateUserReply) Reset() { 441 | *x = UpdateUserReply{} 442 | if protoimpl.UnsafeEnabled { 443 | mi := &file_example_v1_greeter_proto_msgTypes[5] 444 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 445 | ms.StoreMessageInfo(mi) 446 | } 447 | } 448 | 449 | func (x *UpdateUserReply) String() string { 450 | return protoimpl.X.MessageStringOf(x) 451 | } 452 | 453 | func (*UpdateUserReply) ProtoMessage() {} 454 | 455 | func (x *UpdateUserReply) ProtoReflect() protoreflect.Message { 456 | mi := &file_example_v1_greeter_proto_msgTypes[5] 457 | if protoimpl.UnsafeEnabled && x != nil { 458 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 459 | if ms.LoadMessageInfo() == nil { 460 | ms.StoreMessageInfo(mi) 461 | } 462 | return ms 463 | } 464 | return mi.MessageOf(x) 465 | } 466 | 467 | // Deprecated: Use UpdateUserReply.ProtoReflect.Descriptor instead. 468 | func (*UpdateUserReply) Descriptor() ([]byte, []int) { 469 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{5} 470 | } 471 | 472 | func (x *UpdateUserReply) GetMessage() string { 473 | if x != nil { 474 | return x.Message 475 | } 476 | return "" 477 | } 478 | 479 | func (x *UpdateUserReply) GetUsername() string { 480 | if x != nil { 481 | return x.Username 482 | } 483 | return "" 484 | } 485 | 486 | // The request message containing the user's name. 487 | type UserRequest struct { 488 | state protoimpl.MessageState 489 | sizeCache protoimpl.SizeCache 490 | unknownFields protoimpl.UnknownFields 491 | 492 | Phone string `protobuf:"bytes,1,opt,name=phone,proto3" json:"phone,omitempty"` 493 | Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` 494 | Foo Foo `protobuf:"varint,3,opt,name=foo,proto3,enum=v1.Foo" json:"foo,omitempty"` 495 | UserAddr *UserAddr `protobuf:"bytes,4,opt,name=user_addr,json=userAddr,proto3" json:"user_addr,omitempty"` 496 | } 497 | 498 | func (x *UserRequest) Reset() { 499 | *x = UserRequest{} 500 | if protoimpl.UnsafeEnabled { 501 | mi := &file_example_v1_greeter_proto_msgTypes[6] 502 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 503 | ms.StoreMessageInfo(mi) 504 | } 505 | } 506 | 507 | func (x *UserRequest) String() string { 508 | return protoimpl.X.MessageStringOf(x) 509 | } 510 | 511 | func (*UserRequest) ProtoMessage() {} 512 | 513 | func (x *UserRequest) ProtoReflect() protoreflect.Message { 514 | mi := &file_example_v1_greeter_proto_msgTypes[6] 515 | if protoimpl.UnsafeEnabled && x != nil { 516 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 517 | if ms.LoadMessageInfo() == nil { 518 | ms.StoreMessageInfo(mi) 519 | } 520 | return ms 521 | } 522 | return mi.MessageOf(x) 523 | } 524 | 525 | // Deprecated: Use UserRequest.ProtoReflect.Descriptor instead. 526 | func (*UserRequest) Descriptor() ([]byte, []int) { 527 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{6} 528 | } 529 | 530 | func (x *UserRequest) GetPhone() string { 531 | if x != nil { 532 | return x.Phone 533 | } 534 | return "" 535 | } 536 | 537 | func (x *UserRequest) GetEmail() string { 538 | if x != nil { 539 | return x.Email 540 | } 541 | return "" 542 | } 543 | 544 | func (x *UserRequest) GetFoo() Foo { 545 | if x != nil { 546 | return x.Foo 547 | } 548 | return Foo_DEFAULT_BAR 549 | } 550 | 551 | func (x *UserRequest) GetUserAddr() *UserAddr { 552 | if x != nil { 553 | return x.UserAddr 554 | } 555 | return nil 556 | } 557 | 558 | type UserAddr struct { 559 | state protoimpl.MessageState 560 | sizeCache protoimpl.SizeCache 561 | unknownFields protoimpl.UnknownFields 562 | 563 | Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` 564 | } 565 | 566 | func (x *UserAddr) Reset() { 567 | *x = UserAddr{} 568 | if protoimpl.UnsafeEnabled { 569 | mi := &file_example_v1_greeter_proto_msgTypes[7] 570 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 571 | ms.StoreMessageInfo(mi) 572 | } 573 | } 574 | 575 | func (x *UserAddr) String() string { 576 | return protoimpl.X.MessageStringOf(x) 577 | } 578 | 579 | func (*UserAddr) ProtoMessage() {} 580 | 581 | func (x *UserAddr) ProtoReflect() protoreflect.Message { 582 | mi := &file_example_v1_greeter_proto_msgTypes[7] 583 | if protoimpl.UnsafeEnabled && x != nil { 584 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 585 | if ms.LoadMessageInfo() == nil { 586 | ms.StoreMessageInfo(mi) 587 | } 588 | return ms 589 | } 590 | return mi.MessageOf(x) 591 | } 592 | 593 | // Deprecated: Use UserAddr.ProtoReflect.Descriptor instead. 594 | func (*UserAddr) Descriptor() ([]byte, []int) { 595 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{7} 596 | } 597 | 598 | func (x *UserAddr) GetAddr() string { 599 | if x != nil { 600 | return x.Addr 601 | } 602 | return "" 603 | } 604 | 605 | // The response message containing the greetings 606 | type UserReply struct { 607 | state protoimpl.MessageState 608 | sizeCache protoimpl.SizeCache 609 | unknownFields protoimpl.UnknownFields 610 | 611 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 612 | } 613 | 614 | func (x *UserReply) Reset() { 615 | *x = UserReply{} 616 | if protoimpl.UnsafeEnabled { 617 | mi := &file_example_v1_greeter_proto_msgTypes[8] 618 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 619 | ms.StoreMessageInfo(mi) 620 | } 621 | } 622 | 623 | func (x *UserReply) String() string { 624 | return protoimpl.X.MessageStringOf(x) 625 | } 626 | 627 | func (*UserReply) ProtoMessage() {} 628 | 629 | func (x *UserReply) ProtoReflect() protoreflect.Message { 630 | mi := &file_example_v1_greeter_proto_msgTypes[8] 631 | if protoimpl.UnsafeEnabled && x != nil { 632 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 633 | if ms.LoadMessageInfo() == nil { 634 | ms.StoreMessageInfo(mi) 635 | } 636 | return ms 637 | } 638 | return mi.MessageOf(x) 639 | } 640 | 641 | // Deprecated: Use UserReply.ProtoReflect.Descriptor instead. 642 | func (*UserReply) Descriptor() ([]byte, []int) { 643 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{8} 644 | } 645 | 646 | func (x *UserReply) GetMessage() string { 647 | if x != nil { 648 | return x.Message 649 | } 650 | return "" 651 | } 652 | 653 | type UserReplys struct { 654 | state protoimpl.MessageState 655 | sizeCache protoimpl.SizeCache 656 | unknownFields protoimpl.UnknownFields 657 | 658 | UserList []*UserReply `protobuf:"bytes,1,rep,name=userList,proto3" json:"userList,omitempty"` 659 | // The maximum number of books to return. The service may return fewer than 660 | // this value. 661 | // If unspecified, at most 50 books will be returned. 662 | // The maximum value is 1000; values above 1000 will be coerced to 1000. 663 | PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` 664 | // A page token, received from a previous `ListBooks` call. 665 | // Provide this to retrieve the subsequent page. 666 | // 667 | // When paginating, all other parameters provided to `ListBooks` must match 668 | // the call that provided the page token. 669 | PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` 670 | } 671 | 672 | func (x *UserReplys) Reset() { 673 | *x = UserReplys{} 674 | if protoimpl.UnsafeEnabled { 675 | mi := &file_example_v1_greeter_proto_msgTypes[9] 676 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 677 | ms.StoreMessageInfo(mi) 678 | } 679 | } 680 | 681 | func (x *UserReplys) String() string { 682 | return protoimpl.X.MessageStringOf(x) 683 | } 684 | 685 | func (*UserReplys) ProtoMessage() {} 686 | 687 | func (x *UserReplys) ProtoReflect() protoreflect.Message { 688 | mi := &file_example_v1_greeter_proto_msgTypes[9] 689 | if protoimpl.UnsafeEnabled && x != nil { 690 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 691 | if ms.LoadMessageInfo() == nil { 692 | ms.StoreMessageInfo(mi) 693 | } 694 | return ms 695 | } 696 | return mi.MessageOf(x) 697 | } 698 | 699 | // Deprecated: Use UserReplys.ProtoReflect.Descriptor instead. 700 | func (*UserReplys) Descriptor() ([]byte, []int) { 701 | return file_example_v1_greeter_proto_rawDescGZIP(), []int{9} 702 | } 703 | 704 | func (x *UserReplys) GetUserList() []*UserReply { 705 | if x != nil { 706 | return x.UserList 707 | } 708 | return nil 709 | } 710 | 711 | func (x *UserReplys) GetPageSize() int32 { 712 | if x != nil { 713 | return x.PageSize 714 | } 715 | return 0 716 | } 717 | 718 | func (x *UserReplys) GetPageToken() string { 719 | if x != nil { 720 | return x.PageToken 721 | } 722 | return "" 723 | } 724 | 725 | var File_example_v1_greeter_proto protoreflect.FileDescriptor 726 | 727 | var file_example_v1_greeter_proto_rawDesc = []byte{ 728 | 0x0a, 0x18, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72, 0x65, 729 | 0x65, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x76, 0x31, 0x1a, 0x1c, 730 | 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 731 | 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 732 | 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 733 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xed, 0x01, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 734 | 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 735 | 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x69, 736 | 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x69, 0x63, 0x65, 0x12, 0x10, 737 | 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69, 0x64, 738 | 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 739 | 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x72, 0x70, 740 | 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 741 | 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x72, 0x70, 0x75, 742 | 0x73, 0x52, 0x06, 0x63, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x22, 0x5a, 0x0a, 0x06, 0x43, 0x6f, 0x72, 743 | 0x70, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x49, 0x56, 0x45, 0x52, 0x53, 0x41, 0x4c, 744 | 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x57, 0x45, 0x42, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x49, 745 | 0x4d, 0x41, 0x47, 0x45, 0x53, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 746 | 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x45, 0x57, 0x53, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 747 | 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x54, 0x53, 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x49, 748 | 0x44, 0x45, 0x4f, 0x10, 0x06, 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 749 | 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 750 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4b, 0x0a, 751 | 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 752 | 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 753 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 754 | 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 755 | 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x27, 0x0a, 0x0f, 0x43, 0x72, 756 | 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a, 757 | 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 758 | 0x6b, 0x65, 0x6e, 0x22, 0x5b, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 759 | 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 760 | 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 761 | 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 762 | 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 763 | 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 764 | 0x22, 0x47, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 765 | 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 766 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 767 | 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 768 | 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x7f, 0x0a, 0x0b, 0x55, 0x73, 0x65, 769 | 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x6f, 0x6e, 770 | 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x14, 771 | 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 772 | 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x19, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 773 | 0x0e, 0x32, 0x07, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x6f, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 774 | 0x29, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 775 | 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 776 | 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x22, 0x1e, 0x0a, 0x08, 0x55, 0x73, 777 | 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 778 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x22, 0x25, 0x0a, 0x09, 0x55, 0x73, 779 | 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 780 | 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 781 | 0x65, 0x22, 0x73, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x73, 0x12, 782 | 0x29, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 783 | 0x0b, 0x32, 0x0d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 784 | 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 785 | 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 786 | 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 787 | 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 788 | 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x2a, 0x34, 0x0a, 0x03, 0x46, 0x6f, 0x6f, 0x12, 0x0f, 0x0a, 789 | 0x0b, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x42, 0x41, 0x52, 0x10, 0x00, 0x12, 0x0d, 790 | 0x0a, 0x09, 0x42, 0x41, 0x52, 0x5f, 0x42, 0x45, 0x4c, 0x4c, 0x53, 0x10, 0x01, 0x12, 0x0d, 0x0a, 791 | 0x09, 0x42, 0x41, 0x52, 0x5f, 0x42, 0x5f, 0x43, 0x55, 0x45, 0x10, 0x02, 0x32, 0xb6, 0x03, 0x0a, 792 | 0x07, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 793 | 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x10, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 794 | 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 795 | 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 796 | 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 797 | 0x65, 0x7d, 0x2f, 0x68, 0x69, 0x2f, 0x7b, 0x6e, 0x69, 0x63, 0x65, 0x7d, 0x12, 0x4b, 0x0a, 0x0a, 798 | 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x76, 0x31, 0x2e, 799 | 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 800 | 0x74, 0x1a, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 801 | 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0b, 0x22, 0x06, 802 | 0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x3a, 0x01, 0x2a, 0x12, 0x5c, 0x0a, 0x0a, 0x55, 0x70, 0x64, 803 | 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 804 | 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 805 | 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 806 | 0x70, 0x6c, 0x79, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x32, 0x17, 0x2f, 0x72, 0x65, 807 | 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x65, 0x64, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x7b, 0x70, 0x68, 808 | 0x6f, 0x6e, 0x65, 0x7d, 0x3a, 0x01, 0x2a, 0x12, 0x42, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 809 | 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0f, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 810 | 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 811 | 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x2a, 0x0c, 0x2f, 812 | 0x75, 0x73, 0x72, 0x2f, 0x7b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x7d, 0x12, 0x42, 0x0a, 0x09, 0x4c, 813 | 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x0f, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 814 | 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 815 | 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x73, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 816 | 0x0e, 0x12, 0x0c, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x7b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x7d, 0x1a, 817 | 0x24, 0xca, 0x41, 0x06, 0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0xd2, 0x41, 0x18, 0x2f, 0x72, 0x65, 818 | 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x65, 0x64, 0x2c, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 819 | 0x63, 0x74, 0x65, 0x64, 0x31, 0x42, 0x1f, 0x5a, 0x1d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 820 | 0x67, 0x65, 0x6e, 0x2d, 0x65, 0x63, 0x68, 0x6f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 821 | 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 822 | } 823 | 824 | var ( 825 | file_example_v1_greeter_proto_rawDescOnce sync.Once 826 | file_example_v1_greeter_proto_rawDescData = file_example_v1_greeter_proto_rawDesc 827 | ) 828 | 829 | func file_example_v1_greeter_proto_rawDescGZIP() []byte { 830 | file_example_v1_greeter_proto_rawDescOnce.Do(func() { 831 | file_example_v1_greeter_proto_rawDescData = protoimpl.X.CompressGZIP(file_example_v1_greeter_proto_rawDescData) 832 | }) 833 | return file_example_v1_greeter_proto_rawDescData 834 | } 835 | 836 | var file_example_v1_greeter_proto_enumTypes = make([]protoimpl.EnumInfo, 2) 837 | var file_example_v1_greeter_proto_msgTypes = make([]protoimpl.MessageInfo, 10) 838 | var file_example_v1_greeter_proto_goTypes = []interface{}{ 839 | (Foo)(0), // 0: v1.Foo 840 | (HelloRequest_Corpus)(0), // 1: v1.HelloRequest.Corpus 841 | (*HelloRequest)(nil), // 2: v1.HelloRequest 842 | (*HelloReply)(nil), // 3: v1.HelloReply 843 | (*CreateUserRequest)(nil), // 4: v1.CreateUserRequest 844 | (*CreateUserReply)(nil), // 5: v1.CreateUserReply 845 | (*UpdateUserRequest)(nil), // 6: v1.UpdateUserRequest 846 | (*UpdateUserReply)(nil), // 7: v1.UpdateUserReply 847 | (*UserRequest)(nil), // 8: v1.UserRequest 848 | (*UserAddr)(nil), // 9: v1.UserAddr 849 | (*UserReply)(nil), // 10: v1.UserReply 850 | (*UserReplys)(nil), // 11: v1.UserReplys 851 | } 852 | var file_example_v1_greeter_proto_depIdxs = []int32{ 853 | 1, // 0: v1.HelloRequest.corpus:type_name -> v1.HelloRequest.Corpus 854 | 0, // 1: v1.UserRequest.foo:type_name -> v1.Foo 855 | 9, // 2: v1.UserRequest.user_addr:type_name -> v1.UserAddr 856 | 10, // 3: v1.UserReplys.userList:type_name -> v1.UserReply 857 | 2, // 4: v1.Greeter.SayHello:input_type -> v1.HelloRequest 858 | 4, // 5: v1.Greeter.CreateUser:input_type -> v1.CreateUserRequest 859 | 6, // 6: v1.Greeter.UpdateUser:input_type -> v1.UpdateUserRequest 860 | 8, // 7: v1.Greeter.DeleteUser:input_type -> v1.UserRequest 861 | 8, // 8: v1.Greeter.ListUsers:input_type -> v1.UserRequest 862 | 3, // 9: v1.Greeter.SayHello:output_type -> v1.HelloReply 863 | 5, // 10: v1.Greeter.CreateUser:output_type -> v1.CreateUserReply 864 | 7, // 11: v1.Greeter.UpdateUser:output_type -> v1.UpdateUserReply 865 | 10, // 12: v1.Greeter.DeleteUser:output_type -> v1.UserReply 866 | 11, // 13: v1.Greeter.ListUsers:output_type -> v1.UserReplys 867 | 9, // [9:14] is the sub-list for method output_type 868 | 4, // [4:9] is the sub-list for method input_type 869 | 4, // [4:4] is the sub-list for extension type_name 870 | 4, // [4:4] is the sub-list for extension extendee 871 | 0, // [0:4] is the sub-list for field type_name 872 | } 873 | 874 | func init() { file_example_v1_greeter_proto_init() } 875 | func file_example_v1_greeter_proto_init() { 876 | if File_example_v1_greeter_proto != nil { 877 | return 878 | } 879 | if !protoimpl.UnsafeEnabled { 880 | file_example_v1_greeter_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 881 | switch v := v.(*HelloRequest); i { 882 | case 0: 883 | return &v.state 884 | case 1: 885 | return &v.sizeCache 886 | case 2: 887 | return &v.unknownFields 888 | default: 889 | return nil 890 | } 891 | } 892 | file_example_v1_greeter_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 893 | switch v := v.(*HelloReply); i { 894 | case 0: 895 | return &v.state 896 | case 1: 897 | return &v.sizeCache 898 | case 2: 899 | return &v.unknownFields 900 | default: 901 | return nil 902 | } 903 | } 904 | file_example_v1_greeter_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 905 | switch v := v.(*CreateUserRequest); i { 906 | case 0: 907 | return &v.state 908 | case 1: 909 | return &v.sizeCache 910 | case 2: 911 | return &v.unknownFields 912 | default: 913 | return nil 914 | } 915 | } 916 | file_example_v1_greeter_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { 917 | switch v := v.(*CreateUserReply); i { 918 | case 0: 919 | return &v.state 920 | case 1: 921 | return &v.sizeCache 922 | case 2: 923 | return &v.unknownFields 924 | default: 925 | return nil 926 | } 927 | } 928 | file_example_v1_greeter_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { 929 | switch v := v.(*UpdateUserRequest); i { 930 | case 0: 931 | return &v.state 932 | case 1: 933 | return &v.sizeCache 934 | case 2: 935 | return &v.unknownFields 936 | default: 937 | return nil 938 | } 939 | } 940 | file_example_v1_greeter_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { 941 | switch v := v.(*UpdateUserReply); i { 942 | case 0: 943 | return &v.state 944 | case 1: 945 | return &v.sizeCache 946 | case 2: 947 | return &v.unknownFields 948 | default: 949 | return nil 950 | } 951 | } 952 | file_example_v1_greeter_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { 953 | switch v := v.(*UserRequest); i { 954 | case 0: 955 | return &v.state 956 | case 1: 957 | return &v.sizeCache 958 | case 2: 959 | return &v.unknownFields 960 | default: 961 | return nil 962 | } 963 | } 964 | file_example_v1_greeter_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { 965 | switch v := v.(*UserAddr); i { 966 | case 0: 967 | return &v.state 968 | case 1: 969 | return &v.sizeCache 970 | case 2: 971 | return &v.unknownFields 972 | default: 973 | return nil 974 | } 975 | } 976 | file_example_v1_greeter_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { 977 | switch v := v.(*UserReply); i { 978 | case 0: 979 | return &v.state 980 | case 1: 981 | return &v.sizeCache 982 | case 2: 983 | return &v.unknownFields 984 | default: 985 | return nil 986 | } 987 | } 988 | file_example_v1_greeter_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { 989 | switch v := v.(*UserReplys); i { 990 | case 0: 991 | return &v.state 992 | case 1: 993 | return &v.sizeCache 994 | case 2: 995 | return &v.unknownFields 996 | default: 997 | return nil 998 | } 999 | } 1000 | } 1001 | type x struct{} 1002 | out := protoimpl.TypeBuilder{ 1003 | File: protoimpl.DescBuilder{ 1004 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 1005 | RawDescriptor: file_example_v1_greeter_proto_rawDesc, 1006 | NumEnums: 2, 1007 | NumMessages: 10, 1008 | NumExtensions: 0, 1009 | NumServices: 1, 1010 | }, 1011 | GoTypes: file_example_v1_greeter_proto_goTypes, 1012 | DependencyIndexes: file_example_v1_greeter_proto_depIdxs, 1013 | EnumInfos: file_example_v1_greeter_proto_enumTypes, 1014 | MessageInfos: file_example_v1_greeter_proto_msgTypes, 1015 | }.Build() 1016 | File_example_v1_greeter_proto = out.File 1017 | file_example_v1_greeter_proto_rawDesc = nil 1018 | file_example_v1_greeter_proto_goTypes = nil 1019 | file_example_v1_greeter_proto_depIdxs = nil 1020 | } 1021 | -------------------------------------------------------------------------------- /example/v1/greeter.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v1; 4 | 5 | import "google/api/annotations.proto"; 6 | //import "google/api/routing.proto"; 7 | import "google/api/client.proto"; 8 | //import "google/api/field_behavior.proto"; 9 | //import "google/api/resource.proto"; 10 | //import "google/protobuf/empty.proto"; 11 | //import "google/protobuf/field_mask.proto"; 12 | //import "google/protobuf/timestamp.proto"; 13 | 14 | option go_package = "protoc-gen-echo/example/v1;v1"; 15 | 16 | // The greeting service definition. 17 | service Greeter { 18 | //get token URL 19 | option (google.api.default_host) = "/login"; 20 | //need auth root path, can multi path 21 | option (google.api.oauth_scopes) = 22 | "/restricted," 23 | "/restricted1"; 24 | 25 | // Sends a greeting 26 | rpc SayHello (HelloRequest) returns (HelloReply) { 27 | option (google.api.http) = { 28 | get: "/helloworld/{name}/hi/{nice}" 29 | }; 30 | } 31 | 32 | // Create a user 33 | // The /login mapping service option (google.api.default_host) = "/login"; 34 | rpc CreateUser (CreateUserRequest) returns (CreateUserReply) { 35 | option (google.api.http) = { 36 | post: "/login" 37 | body: "*" 38 | }; 39 | } 40 | 41 | // Update a user 42 | // The /restricted/usr/{phone} need auth mapping service option (google.api.oauth_scopes) = 43 | // "/restricted"; 44 | rpc UpdateUser (UpdateUserRequest) returns (UpdateUserReply) { 45 | option (google.api.http) = { 46 | patch: "/restricted/usr/{phone}" 47 | body: "*" 48 | }; 49 | } 50 | 51 | // Delete a user 52 | rpc DeleteUser (UserRequest) returns (UserReply) { 53 | option (google.api.http) = { 54 | delete: "/usr/{phone}" 55 | }; 56 | } 57 | 58 | // Get user list 59 | rpc ListUsers (UserRequest) returns (UserReplys) { 60 | option (google.api.http) = { 61 | get: "/usr/{phone}" 62 | }; 63 | } 64 | } 65 | 66 | // The request message containing the user's name. 67 | message HelloRequest { 68 | enum Corpus { 69 | UNIVERSAL = 0; 70 | WEB = 1; 71 | IMAGES = 2; 72 | LOCAL = 3; 73 | NEWS = 4; 74 | PRODUCTS = 5; 75 | VIDEO = 6; 76 | } 77 | int32 name = 1; 78 | string nice = 2; 79 | int64 uid = 3; 80 | bool authed = 4; 81 | Corpus corpus = 5; 82 | } 83 | 84 | // The response message containing the greetings 85 | message HelloReply { 86 | string message = 1; 87 | } 88 | 89 | // Login request must include username and password field. 90 | message CreateUserRequest { 91 | string username = 1; 92 | string password = 2; 93 | } 94 | 95 | // Login reply must include token field. 96 | message CreateUserReply { 97 | string token = 1; 98 | } 99 | 100 | // The request message containing the user's name. 101 | message UpdateUserRequest { 102 | string username = 1; 103 | string phone = 2; 104 | string email = 3; 105 | } 106 | 107 | // The response message containing the greetings 108 | message UpdateUserReply { 109 | string message = 1; 110 | string username = 2; 111 | } 112 | 113 | enum Foo { 114 | DEFAULT_BAR = 0; 115 | BAR_BELLS = 1; 116 | BAR_B_CUE = 2; 117 | } 118 | // The request message containing the user's name. 119 | message UserRequest { 120 | string phone = 1; 121 | string email = 2; 122 | Foo foo = 3; 123 | UserAddr user_addr = 4; 124 | } 125 | 126 | message UserAddr { 127 | string addr = 1; 128 | } 129 | 130 | // The response message containing the greetings 131 | message UserReply { 132 | string message = 1; 133 | } 134 | 135 | message UserReplys { 136 | repeated UserReply userList = 1; 137 | 138 | // The maximum number of books to return. The service may return fewer than 139 | // this value. 140 | // If unspecified, at most 50 books will be returned. 141 | // The maximum value is 1000; values above 1000 will be coerced to 1000. 142 | int32 page_size = 2; 143 | 144 | // A page token, received from a previous `ListBooks` call. 145 | // Provide this to retrieve the subsequent page. 146 | // 147 | // When paginating, all other parameters provided to `ListBooks` must match 148 | // the call that provided the page token. 149 | string page_token = 3; 150 | } 151 | -------------------------------------------------------------------------------- /example/v1/greeter_handler.pb.go: -------------------------------------------------------------------------------- 1 | // The business logic. 2 | // versions: 3 | // - protoc-gen-echo v0.1.1 4 | // - protoc v3.12.4 5 | // source: example/v1/greeter.proto 6 | 7 | package v1 8 | 9 | import ( 10 | "encoding/json" 11 | "fmt" 12 | "os" 13 | "time" 14 | 15 | "github.com/golang-jwt/jwt" 16 | "github.com/labstack/echo/v4" 17 | ) 18 | 19 | func GreeterSayHelloBusinessHandler(req *HelloRequest, c echo.Context) (HelloReply, error) { 20 | // Here can put your business logic, can use ORM:github.com/go-woo/protoc-gen-ent 21 | // Below is example business logic code 22 | rj, err := json.Marshal(req) 23 | if err != nil { 24 | return HelloReply{}, err 25 | } 26 | fmt.Printf("Got HelloRequest is: %v\n", string(rj)) 27 | return HelloReply{}, nil 28 | } 29 | 30 | func GreeterCreateUserBusinessHandler(req *CreateUserRequest, c echo.Context) (CreateUserReply, error) { 31 | // Throws unauthorized error 32 | if req.Username != "hello" || req.Password != "world" { 33 | return CreateUserReply{}, echo.ErrUnauthorized 34 | } 35 | // Set custom claims 36 | claims := &JwtCustomClaims{ 37 | Name: "Hello World", 38 | Admin: true, 39 | StandardClaims: jwt.StandardClaims{ 40 | ExpiresAt: time.Now().Add(time.Hour * 72).Unix(), 41 | }, 42 | } 43 | // Create token with claims 44 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 45 | // Generate encoded token and send it as response. 46 | jk := "dangerous" 47 | if os.Getenv("JWTKEY") != "" { 48 | jk = os.Getenv("JWTKEY") 49 | } 50 | t, err := token.SignedString([]byte(jk)) 51 | if err != nil { 52 | return CreateUserReply{}, err 53 | } 54 | 55 | // Here can put your business logic, can use ORM:github.com/go-woo/protoc-gen-ent 56 | // Below is example business logic code 57 | rj, err := json.Marshal(req) 58 | if err != nil { 59 | return CreateUserReply{}, err 60 | } 61 | fmt.Printf("Got CreateUserRequest is: %v\n", string(rj)) 62 | return CreateUserReply{Token: "Bearer " + t}, nil 63 | } 64 | 65 | func GreeterUpdateUserBusinessHandler(req *UpdateUserRequest, c echo.Context) (UpdateUserReply, error) { 66 | user := c.Get("user").(*jwt.Token) 67 | claims := user.Claims.(*JwtCustomClaims) 68 | username := claims.Name 69 | fmt.Printf("Got jwt name is: %v\n", username) 70 | req.Username = username 71 | 72 | // Here can put your business logic, can use ORM:github.com/go-woo/protoc-gen-ent 73 | // Below is example business logic code 74 | rj, err := json.Marshal(req) 75 | if err != nil { 76 | return UpdateUserReply{}, err 77 | } 78 | fmt.Printf("Got UpdateUserRequest is: %v\n", string(rj)) 79 | return UpdateUserReply{}, nil 80 | } 81 | 82 | func GreeterDeleteUserBusinessHandler(req *UserRequest, c echo.Context) (UserReply, error) { 83 | // Here can put your business logic, can use ORM:github.com/go-woo/protoc-gen-ent 84 | // Below is example business logic code 85 | rj, err := json.Marshal(req) 86 | if err != nil { 87 | return UserReply{}, err 88 | } 89 | fmt.Printf("Got UserRequest is: %v\n", string(rj)) 90 | return UserReply{}, nil 91 | } 92 | 93 | func GreeterListUsersBusinessHandler(req *UserRequest, c echo.Context) (UserReplys, error) { 94 | // Here can put your business logic, can use ORM:github.com/go-woo/protoc-gen-ent 95 | // Below is example business logic code 96 | rj, err := json.Marshal(req) 97 | if err != nil { 98 | return UserReplys{}, err 99 | } 100 | fmt.Printf("Got UserRequest is: %v\n", string(rj)) 101 | return UserReplys{}, nil 102 | } 103 | -------------------------------------------------------------------------------- /example/v1/greeter_router.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-echo. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-echo v0.1.1 4 | // - protoc v3.12.4 5 | // source: example/v1/greeter.proto 6 | 7 | package v1 8 | 9 | import ( 10 | "net/http" 11 | "os" 12 | 13 | "github.com/go-woo/protoc-gen-echo/runtime" 14 | "github.com/labstack/echo/v4" 15 | "github.com/labstack/echo/v4/middleware" 16 | ) 17 | 18 | func RegisterGreeterRouter(e *echo.Echo) { 19 | jwtKey := "dangerous" 20 | if os.Getenv("JWTKEY") != "" { 21 | jwtKey = os.Getenv("JWTKEY") 22 | } 23 | config := middleware.JWTConfig{ 24 | Claims: &JwtCustomClaims{}, 25 | SigningKey: []byte(jwtKey), 26 | } 27 | 28 | restricted := e.Group("/restricted") 29 | restricted.Use(middleware.JWTWithConfig(config)) 30 | 31 | restricted1 := e.Group("/restricted1") 32 | restricted1.Use(middleware.JWTWithConfig(config)) 33 | 34 | e.GET("/helloworld/:name/hi/:nice", _Greeter_SayHello0_HTTP_Handler) 35 | 36 | e.POST("/login", _Greeter_CreateUser0_HTTP_Handler) 37 | 38 | restricted.PATCH("/restricted/usr/:phone", _Greeter_UpdateUser0_HTTP_Handler) 39 | e.DELETE("/usr/:phone", _Greeter_DeleteUser0_HTTP_Handler) 40 | 41 | e.GET("/usr/:phone", _Greeter_ListUsers0_HTTP_Handler) 42 | 43 | } 44 | 45 | func _Greeter_SayHello0_HTTP_Handler(c echo.Context) error { 46 | var req *HelloRequest = new(HelloRequest) 47 | uv := c.QueryParams() 48 | return runtime.BindValues(req, uv) 49 | reply, err := GreeterSayHelloBusinessHandler(req, c) 50 | if err != nil { 51 | return err 52 | } 53 | return c.JSON(http.StatusOK, &reply) 54 | } 55 | 56 | func _Greeter_CreateUser0_HTTP_Handler(c echo.Context) error { 57 | var req *CreateUserRequest = new(CreateUserRequest) 58 | if err := c.Bind(req); err != nil { 59 | return err 60 | } 61 | uv := c.QueryParams() 62 | return runtime.BindValues(req, uv) 63 | reply, err := GreeterCreateUserBusinessHandler(req, c) 64 | if err != nil { 65 | return err 66 | } 67 | return c.JSON(http.StatusOK, &reply) 68 | } 69 | 70 | func _Greeter_UpdateUser0_HTTP_Handler(c echo.Context) error { 71 | var req *UpdateUserRequest = new(UpdateUserRequest) 72 | if err := c.Bind(req); err != nil { 73 | return err 74 | } 75 | uv := c.QueryParams() 76 | return runtime.BindValues(req, uv) 77 | reply, err := GreeterUpdateUserBusinessHandler(req, c) 78 | if err != nil { 79 | return err 80 | } 81 | return c.JSON(http.StatusOK, &reply) 82 | } 83 | 84 | func _Greeter_DeleteUser0_HTTP_Handler(c echo.Context) error { 85 | var req *UserRequest = new(UserRequest) 86 | uv := c.QueryParams() 87 | return runtime.BindValues(req, uv) 88 | reply, err := GreeterDeleteUserBusinessHandler(req, c) 89 | if err != nil { 90 | return err 91 | } 92 | return c.JSON(http.StatusOK, &reply) 93 | } 94 | 95 | func _Greeter_ListUsers0_HTTP_Handler(c echo.Context) error { 96 | var req *UserRequest = new(UserRequest) 97 | uv := c.QueryParams() 98 | return runtime.BindValues(req, uv) 99 | reply, err := GreeterListUsersBusinessHandler(req, c) 100 | if err != nil { 101 | return err 102 | } 103 | return c.JSON(http.StatusOK, &reply) 104 | } 105 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-woo/protoc-gen-echo 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/golang-jwt/jwt v3.2.2+incompatible 7 | github.com/labstack/echo/v4 v4.7.2 8 | google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f 9 | google.golang.org/protobuf v1.28.1 10 | ) 11 | 12 | require ( 13 | github.com/labstack/gommon v0.3.1 // indirect 14 | github.com/mattn/go-colorable v0.1.11 // indirect 15 | github.com/mattn/go-isatty v0.0.14 // indirect 16 | github.com/valyala/bytebufferpool v1.0.0 // indirect 17 | github.com/valyala/fasttemplate v1.2.1 // indirect 18 | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect 19 | golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect 20 | golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect 21 | golang.org/x/text v0.3.7 // indirect 22 | golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect 23 | ) 24 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= 5 | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 6 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 7 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 8 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 9 | github.com/labstack/echo/v4 v4.7.2 h1:Kv2/p8OaQ+M6Ex4eGimg9b9e6icoxA42JSlOR3msKtI= 10 | github.com/labstack/echo/v4 v4.7.2/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks= 11 | github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o= 12 | github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= 13 | github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= 14 | github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 15 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= 16 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 17 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 18 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 19 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 20 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 21 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 22 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 23 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 24 | github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= 25 | github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= 26 | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= 27 | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 28 | golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= 29 | golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 30 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 31 | golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 32 | golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4= 33 | golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 34 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 35 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 36 | golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= 37 | golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 38 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 39 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 40 | google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f h1:XVHpVMvPs4MtH3h6cThzKs2snNexcfd35vQx2T3IuIY= 41 | google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= 42 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 43 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 44 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 45 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 46 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 47 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 48 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 49 | -------------------------------------------------------------------------------- /http.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "google.golang.org/genproto/googleapis/api/annotations" 7 | "google.golang.org/protobuf/compiler/protogen" 8 | "google.golang.org/protobuf/proto" 9 | "google.golang.org/protobuf/reflect/protoreflect" 10 | "google.golang.org/protobuf/types/descriptorpb" 11 | "os" 12 | "regexp" 13 | "strings" 14 | ) 15 | 16 | var methodSets = make(map[string]int) 17 | 18 | // generateRouterFile generates a _router.pb.go. 19 | func generateRouterFile(gen *protogen.Plugin, file *protogen.File, omitempty bool) *protogen.GeneratedFile { 20 | if len(file.Services) == 0 || (omitempty && !hasHTTPRule(file.Services)) { 21 | return nil 22 | } 23 | fileRouter := file.GeneratedFilenamePrefix + "_router.pb.go" 24 | g := gen.NewGeneratedFile(fileRouter, file.GoImportPath) 25 | g.P("// Code generated by protoc-gen-echo. DO NOT EDIT.") 26 | g.P("// versions:") 27 | g.P(fmt.Sprintf("// - protoc-gen-echo %s", version)) 28 | g.P("// - protoc ", protocVersion(gen)) 29 | if file.Proto.GetOptions().GetDeprecated() { 30 | g.P("// ", file.Desc.Path(), " is a deprecated file.") 31 | } else { 32 | g.P("// source: ", file.Desc.Path()) 33 | } 34 | g.P() 35 | g.P("package ", file.GoPackageName) 36 | g.P() 37 | generateFileContent(gen, file, g, omitempty, routerTemplate) 38 | return g 39 | } 40 | 41 | // generateHandlerFile generates a _handler.pb.go. 42 | func generateHandlerFile(gen *protogen.Plugin, file *protogen.File, omitempty bool) *protogen.GeneratedFile { 43 | if len(file.Services) == 0 || (omitempty && !hasHTTPRule(file.Services)) { 44 | return nil 45 | } 46 | handlerFile := file.GeneratedFilenamePrefix + "_handler.pb.go" 47 | //if file exist should don't generate 48 | if _, err := os.Stat(handlerFile); !errors.Is(err, os.ErrNotExist) { 49 | return nil 50 | } 51 | 52 | g := gen.NewGeneratedFile(handlerFile, file.GoImportPath) 53 | g.P("// The business logic.") 54 | g.P("// versions:") 55 | g.P(fmt.Sprintf("// - protoc-gen-echo %s", version)) 56 | g.P("// - protoc ", protocVersion(gen)) 57 | if file.Proto.GetOptions().GetDeprecated() { 58 | g.P("// ", file.Desc.Path(), " is a deprecated file.") 59 | } else { 60 | g.P("// source: ", file.Desc.Path()) 61 | } 62 | g.P() 63 | g.P("package ", file.GoPackageName) 64 | g.P() 65 | generateFileContent(gen, file, g, omitempty, handlerTemplate) 66 | return g 67 | } 68 | 69 | // generateAuthTypeFile generates a auth_type.pb.go. 70 | func generateAuthTypeFile(gen *protogen.Plugin, file *protogen.File, omitempty bool) *protogen.GeneratedFile { 71 | if len(file.Services) == 0 || (omitempty && !hasHTTPRule(file.Services)) { 72 | return nil 73 | } 74 | authFile := file.GeneratedFilenamePrefix + "auth_type.pb.go" 75 | if last := strings.LastIndex(file.GeneratedFilenamePrefix, "/"); last != -1 { 76 | authFile = file.GeneratedFilenamePrefix[0:last] + "/auth_type.pb.go" 77 | } 78 | //if file exist should don't generate 79 | if _, err := os.Stat(authFile); !errors.Is(err, os.ErrNotExist) { 80 | return nil 81 | } 82 | 83 | g := gen.NewGeneratedFile(authFile, file.GoImportPath) 84 | g.P("// Auth use data type.") 85 | g.P("// versions:") 86 | g.P(fmt.Sprintf("// - protoc-gen-echo %s", version)) 87 | g.P("// - protoc ", protocVersion(gen)) 88 | if file.Proto.GetOptions().GetDeprecated() { 89 | g.P("// ", file.Desc.Path(), " is a deprecated file.") 90 | } else { 91 | g.P("// source: ", file.Desc.Path()) 92 | } 93 | g.P() 94 | g.P("package ", file.GoPackageName) 95 | g.P() 96 | generateFileContent(gen, file, g, omitempty, authTypeTemplate) 97 | return g 98 | } 99 | 100 | // generateFileContent generates the errors definitions, excluding the package statement. 101 | func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, omitempty bool, tpl string) { 102 | if len(file.Services) == 0 { 103 | return 104 | } 105 | g.P() 106 | 107 | for _, service := range file.Services { 108 | genService(gen, file, g, service, omitempty, tpl) 109 | } 110 | } 111 | 112 | func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, service *protogen.Service, omitempty bool, tpl string) { 113 | if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() { 114 | g.P("//") 115 | g.P(deprecationComment) 116 | } 117 | // HTTP Server. 118 | sd := &serviceDesc{ 119 | ServiceType: service.GoName, 120 | ServiceName: string(service.Desc.FullName()), 121 | Metadata: file.Desc.Path(), 122 | } 123 | 124 | //get default host string=get JWT token URL 125 | host := proto.GetExtension(service.Desc.Options(), annotations.E_DefaultHost).(string) 126 | sd.LoginUrl = host 127 | 128 | //get oauth scopes=JWT root path 129 | oas := proto.GetExtension(service.Desc.Options(), annotations.E_OauthScopes).(string) 130 | //fmt.Fprintf(os.Stderr, "score===========%v\n", oas) 131 | scopes := strings.Split(oas, ",") 132 | for _, scope := range scopes { 133 | sd.JwtRootPaths = append(sd.JwtRootPaths, 134 | &JwtRootPath{RootPath: strings.TrimPrefix(scope, "/")}) 135 | } 136 | hasJwt := false 137 | if len(scopes) > 0 { 138 | hasJwt = true 139 | } 140 | sd.HasJwt = hasJwt 141 | 142 | for _, method := range service.Methods { 143 | if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() { 144 | continue 145 | } 146 | //authorization := false 147 | rule, ok := proto.GetExtension(method.Desc.Options(), annotations.E_Http).(*annotations.HttpRule) 148 | if rule != nil && ok { 149 | for _, bind := range rule.AdditionalBindings { 150 | sd.Methods = append(sd.Methods, buildHTTPRule(g, method, bind, host, scopes)) 151 | } 152 | sd.Methods = append(sd.Methods, buildHTTPRule(g, method, rule, host, scopes)) 153 | } else if !omitempty { 154 | path := fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.Desc.Name()) 155 | sd.Methods = append(sd.Methods, buildMethodDesc(g, method, "POST", path, host, scopes)) 156 | } 157 | } 158 | if len(sd.Methods) != 0 { 159 | g.P(sd.execute(tpl)) 160 | } 161 | } 162 | 163 | func hasHTTPRule(services []*protogen.Service) bool { 164 | for _, service := range services { 165 | for _, method := range service.Methods { 166 | if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() { 167 | continue 168 | } 169 | rule, ok := proto.GetExtension(method.Desc.Options(), annotations.E_Http).(*annotations.HttpRule) 170 | if rule != nil && ok { 171 | return true 172 | } 173 | } 174 | } 175 | return false 176 | } 177 | 178 | func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotations.HttpRule, host string, scopes []string) *methodDesc { 179 | var ( 180 | path string 181 | method string 182 | body string 183 | responseBody string 184 | ) 185 | 186 | switch pattern := rule.Pattern.(type) { 187 | case *annotations.HttpRule_Get: 188 | path = pattern.Get 189 | method = "GET" 190 | case *annotations.HttpRule_Put: 191 | path = pattern.Put 192 | method = "PUT" 193 | case *annotations.HttpRule_Post: 194 | path = pattern.Post 195 | method = "POST" 196 | case *annotations.HttpRule_Delete: 197 | path = pattern.Delete 198 | method = "DELETE" 199 | case *annotations.HttpRule_Patch: 200 | path = pattern.Patch 201 | method = "PATCH" 202 | case *annotations.HttpRule_Custom: 203 | path = pattern.Custom.Path 204 | method = pattern.Custom.Kind 205 | } 206 | body = rule.Body 207 | responseBody = rule.ResponseBody 208 | md := buildMethodDesc(g, m, method, path, host, scopes) 209 | if method == "GET" || method == "DELETE" { 210 | if body != "" { 211 | _, _ = fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: %s %s body should not be declared.\n", method, path) 212 | } 213 | } else { 214 | if body == "" { 215 | _, _ = fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: %s %s does not declare a body.\n", method, path) 216 | } 217 | } 218 | if body == "*" { 219 | md.HasBody = true 220 | md.Body = "" 221 | } else if body != "" { 222 | md.HasBody = true 223 | md.Body = "." + camelCaseVars(body) 224 | } else { 225 | md.HasBody = false 226 | } 227 | if responseBody == "*" { 228 | md.ResponseBody = "" 229 | } else if responseBody != "" { 230 | md.ResponseBody = "." + camelCaseVars(responseBody) 231 | } 232 | 233 | return md 234 | } 235 | 236 | func buildMethodDesc(g *protogen.GeneratedFile, m *protogen.Method, method, path string, host string, scopes []string) *methodDesc { 237 | defer func() { methodSets[m.GoName]++ }() 238 | 239 | //get all rpc-method's input mapping XxxxRequest all field name and conv to GoName 240 | //var rf []*RequestField 241 | //lenFields := m.Desc.Input().Fields().Len() 242 | //for i := 0; i < lenFields; i++ { 243 | // fld := m.Desc.Input().Fields().Get(i) 244 | // ce := buildExpr(string(fld.Name()), camelCaseVars(string(fld.Name())), fld) 245 | // rf = append(rf, &RequestField{ 246 | // ProtoName: string(fld.Name()), 247 | // GoName: camelCaseVars(string(fld.Name())), 248 | // GoType: fld.Kind().String(), 249 | // ConvExpr: ce, 250 | // }) 251 | //} 252 | 253 | inScope := false 254 | isLogin := false 255 | scope := "" 256 | 257 | if path == host { 258 | isLogin = true 259 | } 260 | 261 | for _, v := range scopes { 262 | if strings.Index(path+"/", v+"/") == 0 { 263 | inScope = true 264 | scope = strings.TrimPrefix(v, "/") 265 | path = strings.TrimPrefix(path, scope) 266 | break 267 | } 268 | } 269 | 270 | vars := buildPathVars(path) 271 | 272 | for v, s := range vars { 273 | fields := m.Input.Desc.Fields() 274 | 275 | if s != nil { 276 | path = replacePath(v, *s, path) 277 | } 278 | for _, field := range strings.Split(v, ".") { 279 | if strings.TrimSpace(field) == "" { 280 | continue 281 | } 282 | if strings.Contains(field, ":") { 283 | field = strings.Split(field, ":")[0] 284 | } 285 | fd := fields.ByName(protoreflect.Name(field)) 286 | if fd == nil { 287 | fmt.Fprintf(os.Stderr, "\u001B[31mERROR\u001B[m: The corresponding field '%s' declaration in message could not be found in '%s'\n", v, path) 288 | os.Exit(2) 289 | } 290 | if fd.IsMap() { 291 | fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: The field in path:'%s' shouldn't be a map.\n", v) 292 | } else if fd.IsList() { 293 | fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: The field in path:'%s' shouldn't be a list.\n", v) 294 | } else if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind { 295 | //fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: The field in path:'%s' shouldn't be a message or group follow ent.\n", v) 296 | fields = fd.Message().Fields() 297 | } 298 | } 299 | } 300 | 301 | for v, _ := range vars { 302 | path = replacePath(v, "", path) 303 | } 304 | 305 | return &methodDesc{ 306 | Name: m.GoName, 307 | OriginalName: string(m.Desc.Name()), 308 | Num: methodSets[m.GoName], 309 | Request: g.QualifiedGoIdent(m.Input.GoIdent), 310 | Reply: g.QualifiedGoIdent(m.Output.GoIdent), 311 | Path: path, 312 | Method: method, 313 | HasVars: len(vars) > 0, 314 | //Fields: rf, 315 | DefaultHost: host, 316 | InScope: inScope, 317 | Scope: scope, 318 | IsLogin: isLogin, 319 | } 320 | } 321 | 322 | func buildPathVars(path string) (res map[string]*string) { 323 | if strings.HasSuffix(path, "/") { 324 | fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: Path %s should not end with \"/\" \n", path) 325 | } 326 | res = make(map[string]*string) 327 | pattern := regexp.MustCompile(`(?i){([a-z\.0-9_\s]*)=?([^{}]*)}`) 328 | matches := pattern.FindAllStringSubmatch(path, -1) 329 | for _, m := range matches { 330 | name := strings.TrimSpace(m[1]) 331 | if len(name) > 1 && len(m[2]) > 0 { 332 | res[name] = &m[2] 333 | } else { 334 | res[name] = nil 335 | } 336 | } 337 | return 338 | } 339 | 340 | func replacePath(name string, value string, path string) string { 341 | pattern := regexp.MustCompile(fmt.Sprintf(`(?i){([\s]*%s[\s]*)=?([^{}]*)}`, name)) 342 | idx := pattern.FindStringIndex(path) 343 | if len(idx) > 0 { 344 | path = fmt.Sprintf("%s:%s%s", 345 | path[:idx[0]], // The start of the match 346 | name, 347 | path[idx[1]:], 348 | ) 349 | } 350 | return path 351 | } 352 | 353 | func camelCaseVars(s string) string { 354 | subs := strings.Split(s, ".") 355 | vars := make([]string, 0, len(subs)) 356 | for _, sub := range subs { 357 | vars = append(vars, camelCase(sub)) 358 | } 359 | return strings.Join(vars, ".") 360 | } 361 | 362 | // camelCase returns the CamelCased name. 363 | // If there is an interior underscore followed by a lower case letter, 364 | // drop the underscore and convert the letter to upper case. 365 | // There is a remote possibility of this rewrite causing a name collision, 366 | // but it's so remote we're prepared to pretend it's nonexistent - since the 367 | // C++ generator lowercases names, it's extremely unlikely to have two fields 368 | // with different capitalizations. 369 | // In short, _my_field_name_2 becomes XMyFieldName_2. 370 | func camelCase(s string) string { 371 | if s == "" { 372 | return "" 373 | } 374 | t := make([]byte, 0, 32) 375 | i := 0 376 | if s[0] == '_' { 377 | // Need a capital letter; drop the '_'. 378 | t = append(t, 'X') 379 | i++ 380 | } 381 | // Invariant: if the next letter is lower case, it must be converted 382 | // to upper case. 383 | // That is, we process a word at a time, where words are marked by _ or 384 | // upper case letter. Digits are treated as words. 385 | for ; i < len(s); i++ { 386 | c := s[i] 387 | if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) { 388 | continue // Skip the underscore in s. 389 | } 390 | if isASCIIDigit(c) { 391 | t = append(t, c) 392 | continue 393 | } 394 | // Assume we have a letter now - if not, it's a bogus identifier. 395 | // The next word is a sequence of characters that must start upper case. 396 | if isASCIILower(c) { 397 | c ^= ' ' // Make it a capital letter. 398 | } 399 | t = append(t, c) // Guaranteed not lower case. 400 | // Accept lower case sequence that follows. 401 | for i+1 < len(s) && isASCIILower(s[i+1]) { 402 | i++ 403 | t = append(t, s[i]) 404 | } 405 | } 406 | return string(t) 407 | } 408 | 409 | // Is c an ASCII lower-case letter? 410 | func isASCIILower(c byte) bool { 411 | return 'a' <= c && c <= 'z' 412 | } 413 | 414 | // Is c an ASCII digit? 415 | func isASCIIDigit(c byte) bool { 416 | return '0' <= c && c <= '9' 417 | } 418 | 419 | func protocVersion(gen *protogen.Plugin) string { 420 | v := gen.Request.GetCompilerVersion() 421 | if v == nil { 422 | return "(unknown)" 423 | } 424 | var suffix string 425 | if s := v.GetSuffix(); s != "" { 426 | suffix = "-" + s 427 | } 428 | return fmt.Sprintf("v%d.%d.%d%s", v.GetMajor(), v.GetMinor(), v.GetPatch(), suffix) 429 | } 430 | 431 | const deprecationComment = "// Deprecated: Do not use." 432 | -------------------------------------------------------------------------------- /http_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "os" 7 | "testing" 8 | ) 9 | 10 | func Test_buildPathVars(t *testing.T) { 11 | md := buildPathVars("/hello/{name}/asd/{zxc}") 12 | sm, _ := json.Marshal(md) 13 | fmt.Fprintf(os.Stderr, "3=== = %v\n", string(sm)) 14 | 15 | } 16 | 17 | func Test_replacePath(t *testing.T) { 18 | s := replacePath("name", "name", "/hello/{name}/asd/{zxc}") 19 | fmt.Fprintf(os.Stderr, "3=== = %v\n", s) 20 | } 21 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "google.golang.org/protobuf/compiler/protogen" 7 | "google.golang.org/protobuf/types/pluginpb" 8 | ) 9 | 10 | var ( 11 | version = "v0.1.1" 12 | showVersion = flag.Bool("version", false, "print the version and exit") 13 | omitempty = flag.Bool("omitempty", true, "omit if google.api is empty") 14 | ) 15 | 16 | func main() { 17 | flag.Parse() 18 | if *showVersion { 19 | fmt.Printf("protoc-gen-echo %v\n", version) 20 | return 21 | } 22 | protogen.Options{ 23 | ParamFunc: flag.CommandLine.Set, 24 | }.Run(func(gen *protogen.Plugin) error { 25 | gen.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) 26 | for _, f := range gen.Files { 27 | if !f.Generate { 28 | continue 29 | } 30 | generateRouterFile(gen, f, *omitempty) 31 | generateHandlerFile(gen, f, *omitempty) 32 | generateAuthTypeFile(gen, f, *omitempty) 33 | } 34 | return nil 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /runtime/proto_decode.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | import ( 4 | "encoding/base64" 5 | "errors" 6 | "fmt" 7 | "net/url" 8 | "strconv" 9 | "strings" 10 | "time" 11 | 12 | "google.golang.org/protobuf/encoding/protojson" 13 | "google.golang.org/protobuf/types/known/structpb" 14 | 15 | "google.golang.org/genproto/protobuf/field_mask" 16 | "google.golang.org/protobuf/proto" 17 | "google.golang.org/protobuf/reflect/protoreflect" 18 | "google.golang.org/protobuf/reflect/protoregistry" 19 | "google.golang.org/protobuf/types/known/durationpb" 20 | "google.golang.org/protobuf/types/known/timestamppb" 21 | "google.golang.org/protobuf/types/known/wrapperspb" 22 | ) 23 | 24 | const nullStr = "null" 25 | 26 | // BindValues decode url value into proto message. 27 | func BindValues(msg proto.Message, values url.Values) error { 28 | for key, values := range values { 29 | if err := populateFieldValues(msg.ProtoReflect(), strings.Split(key, "."), values); err != nil { 30 | return err 31 | } 32 | } 33 | return nil 34 | } 35 | 36 | func populateFieldValues(v protoreflect.Message, fieldPath []string, values []string) error { 37 | if len(fieldPath) < 1 { 38 | return errors.New("no field path") 39 | } 40 | if len(values) < 1 { 41 | return errors.New("no value provided") 42 | } 43 | 44 | var fd protoreflect.FieldDescriptor 45 | for i, fieldName := range fieldPath { 46 | if fd = getFieldDescriptor(v, fieldName); fd == nil { 47 | // ignore unexpected field. 48 | return nil 49 | } 50 | 51 | if i == len(fieldPath)-1 { 52 | break 53 | } 54 | 55 | if fd.Message() == nil || fd.Cardinality() == protoreflect.Repeated { 56 | if fd.IsMap() && len(fieldPath) > 1 { 57 | // post sub field 58 | return populateMapField(fd, v.Mutable(fd).Map(), []string{fieldPath[1]}, values) 59 | } 60 | return fmt.Errorf("invalid path: %q is not a message", fieldName) 61 | } 62 | 63 | v = v.Mutable(fd).Message() 64 | } 65 | if of := fd.ContainingOneof(); of != nil { 66 | if f := v.WhichOneof(of); f != nil { 67 | return fmt.Errorf("field already set for oneof %q", of.FullName().Name()) 68 | } 69 | } 70 | switch { 71 | case fd.IsList(): 72 | return populateRepeatedField(fd, v.Mutable(fd).List(), values) 73 | case fd.IsMap(): 74 | return populateMapField(fd, v.Mutable(fd).Map(), fieldPath, values) 75 | } 76 | if len(values) > 1 { 77 | return fmt.Errorf("too many values for field %q: %s", fd.FullName().Name(), strings.Join(values, ", ")) 78 | } 79 | return populateField(fd, v, values[0]) 80 | } 81 | 82 | func getFieldDescriptor(v protoreflect.Message, fieldName string) protoreflect.FieldDescriptor { 83 | fields := v.Descriptor().Fields() 84 | var fd protoreflect.FieldDescriptor 85 | if fd = getDescriptorByFieldAndName(fields, fieldName); fd == nil { 86 | if v.Descriptor().FullName() == structMessageFullname { 87 | fd = fields.ByNumber(structFieldsFieldNumber) 88 | } else if len(fieldName) > 2 && strings.HasSuffix(fieldName, "[]") { 89 | fd = getDescriptorByFieldAndName(fields, strings.TrimSuffix(fieldName, "[]")) 90 | } 91 | } 92 | return fd 93 | } 94 | 95 | func getDescriptorByFieldAndName(fields protoreflect.FieldDescriptors, fieldName string) protoreflect.FieldDescriptor { 96 | var fd protoreflect.FieldDescriptor 97 | if fd = fields.ByName(protoreflect.Name(fieldName)); fd == nil { 98 | fd = fields.ByJSONName(fieldName) 99 | } 100 | return fd 101 | } 102 | 103 | func populateField(fd protoreflect.FieldDescriptor, v protoreflect.Message, value string) error { 104 | val, err := parseField(fd, value) 105 | if err != nil { 106 | return fmt.Errorf("parsing field %q: %w", fd.FullName().Name(), err) 107 | } 108 | v.Set(fd, val) 109 | return nil 110 | } 111 | 112 | func populateRepeatedField(fd protoreflect.FieldDescriptor, list protoreflect.List, values []string) error { 113 | for _, value := range values { 114 | v, err := parseField(fd, value) 115 | if err != nil { 116 | return fmt.Errorf("parsing list %q: %w", fd.FullName().Name(), err) 117 | } 118 | list.Append(v) 119 | } 120 | return nil 121 | } 122 | 123 | func populateMapField(fd protoreflect.FieldDescriptor, mp protoreflect.Map, fieldPath []string, values []string) error { 124 | flen := len(fieldPath) 125 | vlen := len(values) 126 | // post sub key. 127 | nkey := flen - 1 128 | key, err := parseField(fd.MapKey(), fieldPath[nkey]) 129 | if err != nil { 130 | return fmt.Errorf("parsing map key %q: %w", fd.FullName().Name(), err) 131 | } 132 | vkey := vlen - 1 133 | value, err := parseField(fd.MapValue(), values[vkey]) 134 | if err != nil { 135 | return fmt.Errorf("parsing map value %q: %w", fd.FullName().Name(), err) 136 | } 137 | mp.Set(key.MapKey(), value) 138 | return nil 139 | } 140 | 141 | func parseField(fd protoreflect.FieldDescriptor, value string) (protoreflect.Value, error) { 142 | switch fd.Kind() { 143 | case protoreflect.BoolKind: 144 | v, err := strconv.ParseBool(value) 145 | if err != nil { 146 | return protoreflect.Value{}, err 147 | } 148 | return protoreflect.ValueOfBool(v), nil 149 | case protoreflect.EnumKind: 150 | enum, err := protoregistry.GlobalTypes.FindEnumByName(fd.Enum().FullName()) 151 | switch { 152 | case errors.Is(err, protoregistry.NotFound): 153 | return protoreflect.Value{}, fmt.Errorf("enum %q is not registered", fd.Enum().FullName()) 154 | case err != nil: 155 | return protoreflect.Value{}, fmt.Errorf("failed to look up enum: %w", err) 156 | } 157 | v := enum.Descriptor().Values().ByName(protoreflect.Name(value)) 158 | if v == nil { 159 | i, err := strconv.ParseInt(value, 10, 32) //nolint:gomnd 160 | if err != nil { 161 | return protoreflect.Value{}, fmt.Errorf("%q is not a valid value", value) 162 | } 163 | v = enum.Descriptor().Values().ByNumber(protoreflect.EnumNumber(i)) 164 | if v == nil { 165 | return protoreflect.Value{}, fmt.Errorf("%q is not a valid value", value) 166 | } 167 | } 168 | return protoreflect.ValueOfEnum(v.Number()), nil 169 | case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: 170 | v, err := strconv.ParseInt(value, 10, 32) //nolint:gomnd 171 | if err != nil { 172 | return protoreflect.Value{}, err 173 | } 174 | return protoreflect.ValueOfInt32(int32(v)), nil 175 | case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: 176 | v, err := strconv.ParseInt(value, 10, 64) //nolint:gomnd 177 | if err != nil { 178 | return protoreflect.Value{}, err 179 | } 180 | return protoreflect.ValueOfInt64(v), nil 181 | case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: 182 | v, err := strconv.ParseUint(value, 10, 32) //nolint:gomnd 183 | if err != nil { 184 | return protoreflect.Value{}, err 185 | } 186 | return protoreflect.ValueOfUint32(uint32(v)), nil 187 | case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: 188 | v, err := strconv.ParseUint(value, 10, 64) //nolint:gomnd 189 | if err != nil { 190 | return protoreflect.Value{}, err 191 | } 192 | return protoreflect.ValueOfUint64(v), nil 193 | case protoreflect.FloatKind: 194 | v, err := strconv.ParseFloat(value, 32) //nolint:gomnd 195 | if err != nil { 196 | return protoreflect.Value{}, err 197 | } 198 | return protoreflect.ValueOfFloat32(float32(v)), nil 199 | case protoreflect.DoubleKind: 200 | v, err := strconv.ParseFloat(value, 64) //nolint:gomnd 201 | if err != nil { 202 | return protoreflect.Value{}, err 203 | } 204 | return protoreflect.ValueOfFloat64(v), nil 205 | case protoreflect.StringKind: 206 | return protoreflect.ValueOfString(value), nil 207 | case protoreflect.BytesKind: 208 | v, err := base64.StdEncoding.DecodeString(value) 209 | if err != nil { 210 | return protoreflect.Value{}, err 211 | } 212 | return protoreflect.ValueOfBytes(v), nil 213 | case protoreflect.MessageKind, protoreflect.GroupKind: 214 | return parseMessage(fd.Message(), value) 215 | default: 216 | panic(fmt.Sprintf("unknown field kind: %v", fd.Kind())) 217 | } 218 | } 219 | 220 | func parseMessage(md protoreflect.MessageDescriptor, value string) (protoreflect.Value, error) { 221 | var msg proto.Message 222 | switch md.FullName() { 223 | case "google.protobuf.Timestamp": 224 | if value == nullStr { 225 | break 226 | } 227 | t, err := time.Parse(time.RFC3339Nano, value) 228 | if err != nil { 229 | return protoreflect.Value{}, err 230 | } 231 | msg = timestamppb.New(t) 232 | case "google.protobuf.Duration": 233 | if value == nullStr { 234 | break 235 | } 236 | d, err := time.ParseDuration(value) 237 | if err != nil { 238 | return protoreflect.Value{}, err 239 | } 240 | msg = durationpb.New(d) 241 | case "google.protobuf.DoubleValue": 242 | v, err := strconv.ParseFloat(value, 64) //nolint:gomnd 243 | if err != nil { 244 | return protoreflect.Value{}, err 245 | } 246 | msg = wrapperspb.Double(v) 247 | case "google.protobuf.FloatValue": 248 | v, err := strconv.ParseFloat(value, 32) //nolint:gomnd 249 | if err != nil { 250 | return protoreflect.Value{}, err 251 | } 252 | msg = wrapperspb.Float(float32(v)) 253 | case "google.protobuf.Int64Value": 254 | v, err := strconv.ParseInt(value, 10, 64) //nolint:gomnd 255 | if err != nil { 256 | return protoreflect.Value{}, err 257 | } 258 | msg = wrapperspb.Int64(v) 259 | case "google.protobuf.Int32Value": 260 | v, err := strconv.ParseInt(value, 10, 32) //nolint:gomnd 261 | if err != nil { 262 | return protoreflect.Value{}, err 263 | } 264 | msg = wrapperspb.Int32(int32(v)) 265 | case "google.protobuf.UInt64Value": 266 | v, err := strconv.ParseUint(value, 10, 64) //nolint:gomnd 267 | if err != nil { 268 | return protoreflect.Value{}, err 269 | } 270 | msg = wrapperspb.UInt64(v) 271 | case "google.protobuf.UInt32Value": 272 | v, err := strconv.ParseUint(value, 10, 32) //nolint:gomnd 273 | if err != nil { 274 | return protoreflect.Value{}, err 275 | } 276 | msg = wrapperspb.UInt32(uint32(v)) 277 | case "google.protobuf.BoolValue": 278 | v, err := strconv.ParseBool(value) 279 | if err != nil { 280 | return protoreflect.Value{}, err 281 | } 282 | msg = wrapperspb.Bool(v) 283 | case "google.protobuf.StringValue": 284 | msg = wrapperspb.String(value) 285 | case "google.protobuf.BytesValue": 286 | v, err := base64.StdEncoding.DecodeString(value) 287 | if err != nil { 288 | if v, err = base64.URLEncoding.DecodeString(value); err != nil { 289 | return protoreflect.Value{}, err 290 | } 291 | } 292 | msg = wrapperspb.Bytes(v) 293 | case "google.protobuf.FieldMask": 294 | fm := &field_mask.FieldMask{} 295 | for _, fv := range strings.Split(value, ",") { 296 | fm.Paths = append(fm.Paths, jsonSnakeCase(fv)) 297 | } 298 | msg = fm 299 | case "google.protobuf.Value": 300 | fm, err := structpb.NewValue(value) 301 | if err != nil { 302 | return protoreflect.Value{}, err 303 | } 304 | msg = fm 305 | case "google.protobuf.Struct": 306 | var v structpb.Struct 307 | if err := protojson.Unmarshal([]byte(value), &v); err != nil { 308 | return protoreflect.Value{}, err 309 | } 310 | msg = &v 311 | default: 312 | return protoreflect.Value{}, fmt.Errorf("unsupported message type: %q", string(md.FullName())) 313 | } 314 | return protoreflect.ValueOfMessage(msg.ProtoReflect()), nil 315 | } 316 | 317 | // jsonSnakeCase converts a camelCase identifier to a snake_case identifier, 318 | // according to the protobuf JSON specification. 319 | // references: https://github.com/protocolbuffers/protobuf-go/blob/master/encoding/protojson/well_known_types.go#L864 320 | func jsonSnakeCase(s string) string { 321 | var b []byte 322 | for i := 0; i < len(s); i++ { // proto identifiers are always ASCII 323 | c := s[i] 324 | if isASCIIUpper(c) { 325 | b = append(b, '_') 326 | c += 'a' - 'A' // convert to lowercase 327 | } 328 | b = append(b, c) 329 | } 330 | return string(b) 331 | } 332 | 333 | func isASCIIUpper(c byte) bool { 334 | return 'A' <= c && c <= 'Z' 335 | } 336 | -------------------------------------------------------------------------------- /runtime/well_known_types.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "math" 7 | "strings" 8 | "time" 9 | 10 | "google.golang.org/protobuf/reflect/protoreflect" 11 | ) 12 | 13 | const ( 14 | // timestamp 15 | timestampMessageFullname protoreflect.FullName = "google.protobuf.Timestamp" 16 | maxTimestampSeconds = 253402300799 17 | minTimestampSeconds = -6213559680013 18 | timestampSecondsFieldNumber protoreflect.FieldNumber = 1 19 | timestampNanosFieldNumber protoreflect.FieldNumber = 2 20 | 21 | // duration 22 | durationMessageFullname protoreflect.FullName = "google.protobuf.Duration" 23 | secondsInNanos = 999999999 24 | durationSecondsFieldNumber protoreflect.FieldNumber = 1 25 | durationNanosFieldNumber protoreflect.FieldNumber = 2 26 | 27 | // bytes 28 | bytesMessageFullname protoreflect.FullName = "google.protobuf.BytesValue" 29 | bytesValueFieldNumber protoreflect.FieldNumber = 1 30 | 31 | // google.protobuf.Struct. 32 | structMessageFullname protoreflect.FullName = "google.protobuf.Struct" 33 | structFieldsFieldNumber protoreflect.FieldNumber = 1 34 | 35 | fieldMaskFullName protoreflect.FullName = "google.protobuf.FieldMask" 36 | ) 37 | 38 | func marshalTimestamp(m protoreflect.Message) (string, error) { 39 | fds := m.Descriptor().Fields() 40 | fdSeconds := fds.ByNumber(timestampSecondsFieldNumber) 41 | fdNanos := fds.ByNumber(timestampNanosFieldNumber) 42 | 43 | secsVal := m.Get(fdSeconds) 44 | nanosVal := m.Get(fdNanos) 45 | secs := secsVal.Int() 46 | nanos := nanosVal.Int() 47 | if secs < minTimestampSeconds || secs > maxTimestampSeconds { 48 | return "", fmt.Errorf("%s: seconds out of range %v", timestampMessageFullname, secs) 49 | } 50 | if nanos < 0 || nanos > secondsInNanos { 51 | return "", fmt.Errorf("%s: nanos out of range %v", timestampMessageFullname, nanos) 52 | } 53 | // Uses RFC 3339, where generated output will be Z-normalized and uses 0, 3, 54 | // 6 or 9 fractional digits. 55 | t := time.Unix(secs, nanos).UTC() 56 | x := t.Format("2006-01-02T15:04:05.000000000") 57 | x = strings.TrimSuffix(x, "000") 58 | x = strings.TrimSuffix(x, "000") 59 | x = strings.TrimSuffix(x, ".000") 60 | return x + "Z", nil 61 | } 62 | 63 | func marshalDuration(m protoreflect.Message) (string, error) { 64 | fds := m.Descriptor().Fields() 65 | fdSeconds := fds.ByNumber(durationSecondsFieldNumber) 66 | fdNanos := fds.ByNumber(durationNanosFieldNumber) 67 | 68 | secsVal := m.Get(fdSeconds) 69 | nanosVal := m.Get(fdNanos) 70 | secs := secsVal.Int() 71 | nanos := nanosVal.Int() 72 | d := time.Duration(secs) * time.Second 73 | overflow := d/time.Second != time.Duration(secs) 74 | d += time.Duration(nanos) * time.Nanosecond 75 | overflow = overflow || (secs < 0 && nanos < 0 && d > 0) 76 | overflow = overflow || (secs > 0 && nanos > 0 && d < 0) 77 | if overflow { 78 | switch { 79 | case secs < 0: 80 | return time.Duration(math.MinInt64).String(), nil 81 | case secs > 0: 82 | return time.Duration(math.MaxInt64).String(), nil 83 | } 84 | } 85 | return d.String(), nil 86 | } 87 | 88 | func marshalBytes(m protoreflect.Message) (string, error) { 89 | fds := m.Descriptor().Fields() 90 | fdBytes := fds.ByNumber(bytesValueFieldNumber) 91 | bytesVal := m.Get(fdBytes) 92 | val := bytesVal.Bytes() 93 | return base64.StdEncoding.EncodeToString(val), nil 94 | } 95 | -------------------------------------------------------------------------------- /template.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "strings" 6 | "text/template" 7 | ) 8 | 9 | var routerTemplate = ` 10 | import ( 11 | "net/http" 12 | "os" 13 | 14 | "github.com/go-woo/protoc-gen-echo/runtime" 15 | "github.com/labstack/echo/v4" 16 | "github.com/labstack/echo/v4/middleware" 17 | ) 18 | {{$svrType := .ServiceType}} 19 | {{$svrName := .ServiceName}} 20 | {{$hasJwt := .HasJwt}} 21 | func Register{{.ServiceType}}Router(e *echo.Echo) { 22 | {{- if $hasJwt}} 23 | jwtKey := "dangerous" 24 | if os.Getenv("JWTKEY") != "" { 25 | jwtKey = os.Getenv("JWTKEY") 26 | } 27 | config := middleware.JWTConfig{ 28 | Claims: &JwtCustomClaims{}, 29 | SigningKey: []byte(jwtKey), 30 | } 31 | {{end}} 32 | {{- range .JwtRootPaths}} 33 | {{.RootPath}} := e.Group("/{{.RootPath}}") 34 | {{.RootPath}}.Use(middleware.JWTWithConfig(config)) 35 | {{end}} 36 | {{- range .Methods}} 37 | {{- if .InScope}} 38 | {{.Scope}}.{{.Method}}("{{.Path}}", _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler) 39 | {{- else}} 40 | e.{{.Method}}("{{.Path}}", _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler) 41 | {{end}} 42 | {{- end}} 43 | } 44 | {{range .Methods}} 45 | func _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler(c echo.Context) error { 46 | var req *{{.Request}} = new({{.Request}}) 47 | {{- if .HasBody}} 48 | if err := c.Bind(req); err != nil { 49 | return err 50 | } 51 | {{- end}} 52 | uv := c.QueryParams() 53 | {{- range .Fields}} 54 | uv.Add("{{.ProtoName}}", c.Param("{{.ProtoName}}")) 55 | {{- end}} 56 | return runtime.BindValues(req, uv) 57 | reply, err := {{$svrType}}{{.Name}}BusinessHandler(req, c) 58 | if err != nil { 59 | return err 60 | } 61 | return c.JSON(http.StatusOK, &reply) 62 | } 63 | {{end}} 64 | ` 65 | 66 | var handlerTemplate = ` 67 | import ( 68 | "encoding/json" 69 | "fmt" 70 | "os" 71 | "time" 72 | 73 | "github.com/go-woo/protoc-gen-echo/runtime" 74 | "github.com/golang-jwt/jwt" 75 | "github.com/labstack/echo/v4" 76 | ) 77 | {{$svrType := .ServiceType}} 78 | {{$svrName := .ServiceName}} 79 | {{$hasJwt := .HasJwt}} 80 | {{range .Methods}} 81 | func {{$svrType}}{{.Name}}BusinessHandler(req *{{.Request}}, c echo.Context) ({{.Reply}}, error) { 82 | {{- if .IsLogin}} 83 | // Throws unauthorized error 84 | if req.Username != "hello" || req.Password != "world" { 85 | return {{.Reply}}{}, echo.ErrUnauthorized 86 | } 87 | // Set custom claims 88 | claims := &JwtCustomClaims{ 89 | Name: "Hello World", 90 | Admin: true, 91 | StandardClaims: jwt.StandardClaims{ 92 | ExpiresAt: time.Now().Add(time.Hour * 72).Unix(), 93 | }, 94 | } 95 | // Create token with claims 96 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 97 | // Generate encoded token and send it as response. 98 | jk := "dangerous" 99 | if os.Getenv("JWTKEY") != "" { 100 | jk = os.Getenv("JWTKEY") 101 | } 102 | t, err := token.SignedString([]byte(jk)) 103 | if err != nil { 104 | return {{.Reply}}{}, err 105 | } 106 | {{end}} 107 | {{- if .InScope}} 108 | user := c.Get("user").(*jwt.Token) 109 | claims := user.Claims.(*JwtCustomClaims) 110 | username := claims.Name 111 | fmt.Printf("Got jwt name is: %v\n", username) 112 | req.Username = username 113 | {{end}} 114 | // Here can put your business logic, can use ORM:github.com/go-woo/protoc-gen-ent 115 | // Below is example business logic code 116 | rj, err := json.Marshal(req) 117 | if err != nil { 118 | return {{.Reply}}{}, err 119 | } 120 | fmt.Printf("Got {{.Request}} is: %v\n", string(rj)) 121 | {{- if .IsLogin}} 122 | return {{.Reply}}{Token: "Bearer " + t}, nil 123 | {{- else}} 124 | return {{.Reply}}{}, nil {{end}} 125 | } 126 | {{end}} 127 | ` 128 | var authTypeTemplate = ` 129 | 130 | import "github.com/golang-jwt/jwt" 131 | 132 | // jwtCustomClaims are custom claims extending default ones. 133 | // See https://github.com/golang-jwt/jwt for more examples 134 | type JwtCustomClaims struct { 135 | Name string ` + "`json:\"name\"`" + ` 136 | Admin bool ` + "`json:\"admin\"`" + ` 137 | jwt.StandardClaims 138 | } 139 | 140 | ` 141 | 142 | type serviceDesc struct { 143 | ServiceType string // Greeter 144 | ServiceName string // example.Greeter 145 | Metadata string // example/v1/greeter.proto 146 | Methods []*methodDesc 147 | MethodSets map[string]*methodDesc 148 | LoginUrl string 149 | HasJwt bool 150 | JwtRootPaths []*JwtRootPath 151 | } 152 | 153 | type JwtRootPath struct { 154 | RootPath string 155 | } 156 | 157 | type methodDesc struct { 158 | Name string 159 | OriginalName string // The parsed original name 160 | Num int 161 | Request string 162 | Reply string 163 | Path string 164 | Method string 165 | HasVars bool 166 | HasBody bool 167 | Body string 168 | ResponseBody string 169 | Fields []*RequestField 170 | DefaultHost string 171 | InScope bool 172 | Scope string 173 | IsLogin bool 174 | } 175 | 176 | type RequestField struct { 177 | ProtoName string 178 | GoName string 179 | GoType string 180 | ConvExpr string 181 | } 182 | 183 | func (s *serviceDesc) execute(tpl string) string { 184 | s.MethodSets = make(map[string]*methodDesc) 185 | for _, m := range s.Methods { 186 | s.MethodSets[m.Name] = m 187 | } 188 | 189 | buf := new(bytes.Buffer) 190 | tmpl, err := template.New("http").Parse(strings.TrimSpace(tpl)) 191 | if err != nil { 192 | panic(err) 193 | } 194 | if err := tmpl.Execute(buf, s); err != nil { 195 | panic(err) 196 | } 197 | return strings.Trim(buf.String(), "\r\n") 198 | } 199 | -------------------------------------------------------------------------------- /third_party/google/api/annotations.proto: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/api/http.proto"; 20 | import "google/protobuf/descriptor.proto"; 21 | 22 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "AnnotationsProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | extend google.protobuf.MethodOptions { 29 | // See `HttpRule`. 30 | HttpRule http = 72295728; 31 | } 32 | -------------------------------------------------------------------------------- /third_party/google/api/client.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/protobuf/descriptor.proto"; 20 | 21 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 22 | option java_multiple_files = true; 23 | option java_outer_classname = "ClientProto"; 24 | option java_package = "com.google.api"; 25 | option objc_class_prefix = "GAPI"; 26 | 27 | 28 | extend google.protobuf.ServiceOptions { 29 | // The hostname for this service. 30 | // This should be specified with no prefix or protocol. 31 | // 32 | // Example: 33 | // 34 | // service Foo { 35 | // option (google.api.default_host) = "foo.googleapi.com"; 36 | // ... 37 | // } 38 | string default_host = 1049; 39 | 40 | // OAuth scopes needed for the client. 41 | // 42 | // Example: 43 | // 44 | // service Foo { 45 | // option (google.api.oauth_scopes) = \ 46 | // "https://www.googleapis.com/auth/cloud-platform"; 47 | // ... 48 | // } 49 | // 50 | // If there is more than one scope, use a comma-separated string: 51 | // 52 | // Example: 53 | // 54 | // service Foo { 55 | // option (google.api.oauth_scopes) = \ 56 | // "https://www.googleapis.com/auth/cloud-platform," 57 | // "https://www.googleapis.com/auth/monitoring"; 58 | // ... 59 | // } 60 | string oauth_scopes = 1050; 61 | } 62 | 63 | 64 | extend google.protobuf.MethodOptions { 65 | // A definition of a client library method signature. 66 | // 67 | // In client libraries, each proto RPC corresponds to one or more methods 68 | // which the end user is able to call, and calls the underlying RPC. 69 | // Normally, this method receives a single argument (a struct or instance 70 | // corresponding to the RPC request object). Defining this field will 71 | // add one or more overloads providing flattened or simpler method signatures 72 | // in some languages. 73 | // 74 | // The fields on the method signature are provided as a comma-separated 75 | // string. 76 | // 77 | // For example, the proto RPC and annotation: 78 | // 79 | // rpc CreateSubscription(CreateSubscriptionRequest) 80 | // returns (Subscription) { 81 | // option (google.api.method_signature) = "name,topic"; 82 | // } 83 | // 84 | // Would add the following Java overload (in addition to the method accepting 85 | // the request object): 86 | // 87 | // public final Subscription createSubscription(String name, String topic) 88 | // 89 | // The following backwards-compatibility guidelines apply: 90 | // 91 | // * Adding this annotation to an unannotated method is backwards 92 | // compatible. 93 | // * Adding this annotation to a method which already has existing 94 | // method signature annotations is backwards compatible if and only if 95 | // the new method signature annotation is last in the sequence. 96 | // * Modifying or removing an existing method signature annotation is 97 | // a breaking change. 98 | // * Re-ordering existing method signature annotations is a breaking 99 | // change. 100 | repeated string method_signature = 1051; 101 | } -------------------------------------------------------------------------------- /third_party/google/api/field_behavior.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/protobuf/descriptor.proto"; 20 | 21 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 22 | option java_multiple_files = true; 23 | option java_outer_classname = "FieldBehaviorProto"; 24 | option java_package = "com.google.api"; 25 | option objc_class_prefix = "GAPI"; 26 | 27 | 28 | // An indicator of the behavior of a given field (for example, that a field 29 | // is required in requests, or given as output but ignored as input). 30 | // This **does not** change the behavior in protocol buffers itself; it only 31 | // denotes the behavior and may affect how API tooling handles the field. 32 | // 33 | // Note: This enum **may** receive new values in the future. 34 | enum FieldBehavior { 35 | // Conventional default for enums. Do not use this. 36 | FIELD_BEHAVIOR_UNSPECIFIED = 0; 37 | 38 | // Specifically denotes a field as optional. 39 | // While all fields in protocol buffers are optional, this may be specified 40 | // for emphasis if appropriate. 41 | OPTIONAL = 1; 42 | 43 | // Denotes a field as required. 44 | // This indicates that the field **must** be provided as part of the request, 45 | // and failure to do so will cause an error (usually `INVALID_ARGUMENT`). 46 | REQUIRED = 2; 47 | 48 | // Denotes a field as output only. 49 | // This indicates that the field is provided in responses, but including the 50 | // field in a request does nothing (the server *must* ignore it and 51 | // *must not* throw an error as a result of the field's presence). 52 | OUTPUT_ONLY = 3; 53 | 54 | // Denotes a field as input only. 55 | // This indicates that the field is provided in requests, and the 56 | // corresponding field is not included in output. 57 | INPUT_ONLY = 4; 58 | 59 | // Denotes a field as immutable. 60 | // This indicates that the field may be set once in a request to create a 61 | // resource, but may not be changed thereafter. 62 | IMMUTABLE = 5; 63 | } 64 | 65 | 66 | extend google.protobuf.FieldOptions { 67 | // A designation of a specific field behavior (required, output only, etc.) 68 | // in protobuf messages. 69 | // 70 | // Examples: 71 | // 72 | // string name = 1 [(google.api.field_behavior) = REQUIRED]; 73 | // State state = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; 74 | // google.protobuf.Duration ttl = 1 75 | // [(google.api.field_behavior) = INPUT_ONLY]; 76 | // google.protobuf.Timestamp expire_time = 1 77 | // [(google.api.field_behavior) = OUTPUT_ONLY, 78 | // (google.api.field_behavior) = IMMUTABLE]; 79 | repeated FieldBehavior field_behavior = 1052; 80 | } -------------------------------------------------------------------------------- /third_party/google/api/http.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | option cc_enable_arenas = true; 20 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 21 | option java_multiple_files = true; 22 | option java_outer_classname = "HttpProto"; 23 | option java_package = "com.google.api"; 24 | option objc_class_prefix = "GAPI"; 25 | 26 | // Defines the HTTP configuration for an API service. It contains a list of 27 | // [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method 28 | // to one or more HTTP REST API methods. 29 | message Http { 30 | // A list of HTTP configuration rules that apply to individual API methods. 31 | // 32 | // **NOTE:** All service configuration rules follow "last one wins" order. 33 | repeated HttpRule rules = 1; 34 | 35 | // When set to true, URL path parameters will be fully URI-decoded except in 36 | // cases of single segment matches in reserved expansion, where "%2F" will be 37 | // left encoded. 38 | // 39 | // The default behavior is to not decode RFC 6570 reserved characters in multi 40 | // segment matches. 41 | bool fully_decode_reserved_expansion = 2; 42 | } 43 | 44 | // # gRPC Transcoding 45 | // 46 | // gRPC Transcoding is a feature for mapping between a gRPC method and one or 47 | // more HTTP REST endpoints. It allows developers to build a single API service 48 | // that supports both gRPC APIs and REST APIs. Many systems, including [Google 49 | // APIs](https://github.com/googleapis/googleapis), 50 | // [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC 51 | // Gateway](https://github.com/grpc-ecosystem/grpc-gateway), 52 | // and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature 53 | // and use it for large scale production services. 54 | // 55 | // `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies 56 | // how different portions of the gRPC request message are mapped to the URL 57 | // path, URL query parameters, and HTTP request body. It also controls how the 58 | // gRPC response message is mapped to the HTTP response body. `HttpRule` is 59 | // typically specified as an `google.api.http` annotation on the gRPC method. 60 | // 61 | // Each mapping specifies a URL path template and an HTTP method. The path 62 | // template may refer to one or more fields in the gRPC request message, as long 63 | // as each field is a non-repeated field with a primitive (non-message) type. 64 | // The path template controls how fields of the request message are mapped to 65 | // the URL path. 66 | // 67 | // Example: 68 | // 69 | // service Messaging { 70 | // rpc GetMessage(GetMessageRequest) returns (Message) { 71 | // option (google.api.http) = { 72 | // get: "/v1/{name=messages/*}" 73 | // }; 74 | // } 75 | // } 76 | // message GetMessageRequest { 77 | // string name = 1; // Mapped to URL path. 78 | // } 79 | // message Message { 80 | // string text = 1; // The resource content. 81 | // } 82 | // 83 | // This enables an HTTP REST to gRPC mapping as below: 84 | // 85 | // HTTP | gRPC 86 | // -----|----- 87 | // `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` 88 | // 89 | // Any fields in the request message which are not bound by the path template 90 | // automatically become HTTP query parameters if there is no HTTP request body. 91 | // For example: 92 | // 93 | // service Messaging { 94 | // rpc GetMessage(GetMessageRequest) returns (Message) { 95 | // option (google.api.http) = { 96 | // get:"/v1/messages/{message_id}" 97 | // }; 98 | // } 99 | // } 100 | // message GetMessageRequest { 101 | // message SubMessage { 102 | // string subfield = 1; 103 | // } 104 | // string message_id = 1; // Mapped to URL path. 105 | // int64 revision = 2; // Mapped to URL query parameter `revision`. 106 | // SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. 107 | // } 108 | // 109 | // This enables a HTTP JSON to RPC mapping as below: 110 | // 111 | // HTTP | gRPC 112 | // -----|----- 113 | // `GET /v1/messages/123456?revision=2&sub.subfield=foo` | 114 | // `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: 115 | // "foo"))` 116 | // 117 | // Note that fields which are mapped to URL query parameters must have a 118 | // primitive type or a repeated primitive type or a non-repeated message type. 119 | // In the case of a repeated type, the parameter can be repeated in the URL 120 | // as `...?param=A¶m=B`. In the case of a message type, each field of the 121 | // message is mapped to a separate parameter, such as 122 | // `...?foo.a=A&foo.b=B&foo.c=C`. 123 | // 124 | // For HTTP methods that allow a request body, the `body` field 125 | // specifies the mapping. Consider a REST update method on the 126 | // message resource collection: 127 | // 128 | // service Messaging { 129 | // rpc UpdateMessage(UpdateMessageRequest) returns (Message) { 130 | // option (google.api.http) = { 131 | // patch: "/v1/messages/{message_id}" 132 | // body: "message" 133 | // }; 134 | // } 135 | // } 136 | // message UpdateMessageRequest { 137 | // string message_id = 1; // mapped to the URL 138 | // Message message = 2; // mapped to the body 139 | // } 140 | // 141 | // The following HTTP JSON to RPC mapping is enabled, where the 142 | // representation of the JSON in the request body is determined by 143 | // protos JSON encoding: 144 | // 145 | // HTTP | gRPC 146 | // -----|----- 147 | // `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: 148 | // "123456" message { text: "Hi!" })` 149 | // 150 | // The special name `*` can be used in the body mapping to define that 151 | // every field not bound by the path template should be mapped to the 152 | // request body. This enables the following alternative definition of 153 | // the update method: 154 | // 155 | // service Messaging { 156 | // rpc UpdateMessage(Message) returns (Message) { 157 | // option (google.api.http) = { 158 | // patch: "/v1/messages/{message_id}" 159 | // body: "*" 160 | // }; 161 | // } 162 | // } 163 | // message Message { 164 | // string message_id = 1; 165 | // string text = 2; 166 | // } 167 | // 168 | // 169 | // The following HTTP JSON to RPC mapping is enabled: 170 | // 171 | // HTTP | gRPC 172 | // -----|----- 173 | // `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: 174 | // "123456" text: "Hi!")` 175 | // 176 | // Note that when using `*` in the body mapping, it is not possible to 177 | // have HTTP parameters, as all fields not bound by the path end in 178 | // the body. This makes this option more rarely used in practice when 179 | // defining REST APIs. The common usage of `*` is in custom methods 180 | // which don't use the URL at all for transferring data. 181 | // 182 | // It is possible to define multiple HTTP methods for one RPC by using 183 | // the `additional_bindings` option. Example: 184 | // 185 | // service Messaging { 186 | // rpc GetMessage(GetMessageRequest) returns (Message) { 187 | // option (google.api.http) = { 188 | // get: "/v1/messages/{message_id}" 189 | // additional_bindings { 190 | // get: "/v1/users/{user_id}/messages/{message_id}" 191 | // } 192 | // }; 193 | // } 194 | // } 195 | // message GetMessageRequest { 196 | // string message_id = 1; 197 | // string user_id = 2; 198 | // } 199 | // 200 | // This enables the following two alternative HTTP JSON to RPC mappings: 201 | // 202 | // HTTP | gRPC 203 | // -----|----- 204 | // `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` 205 | // `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: 206 | // "123456")` 207 | // 208 | // ## Rules for HTTP mapping 209 | // 210 | // 1. Leaf request fields (recursive expansion nested messages in the request 211 | // message) are classified into three categories: 212 | // - Fields referred by the path template. They are passed via the URL path. 213 | // - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP 214 | // request body. 215 | // - All other fields are passed via the URL query parameters, and the 216 | // parameter name is the field path in the request message. A repeated 217 | // field can be represented as multiple query parameters under the same 218 | // name. 219 | // 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields 220 | // are passed via URL path and HTTP request body. 221 | // 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all 222 | // fields are passed via URL path and URL query parameters. 223 | // 224 | // ### Path template syntax 225 | // 226 | // Template = "/" Segments [ Verb ] ; 227 | // Segments = Segment { "/" Segment } ; 228 | // Segment = "*" | "**" | LITERAL | Variable ; 229 | // Variable = "{" FieldPath [ "=" Segments ] "}" ; 230 | // FieldPath = IDENT { "." IDENT } ; 231 | // Verb = ":" LITERAL ; 232 | // 233 | // The syntax `*` matches a single URL path segment. The syntax `**` matches 234 | // zero or more URL path segments, which must be the last part of the URL path 235 | // except the `Verb`. 236 | // 237 | // The syntax `Variable` matches part of the URL path as specified by its 238 | // template. A variable template must not contain other variables. If a variable 239 | // matches a single path segment, its template may be omitted, e.g. `{var}` 240 | // is equivalent to `{var=*}`. 241 | // 242 | // The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` 243 | // contains any reserved character, such characters should be percent-encoded 244 | // before the matching. 245 | // 246 | // If a variable contains exactly one path segment, such as `"{var}"` or 247 | // `"{var=*}"`, when such a variable is expanded into a URL path on the client 248 | // side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The 249 | // server side does the reverse decoding. Such variables show up in the 250 | // [Discovery 251 | // Document](https://developers.google.com/discovery/v1/reference/apis) as 252 | // `{var}`. 253 | // 254 | // If a variable contains multiple path segments, such as `"{var=foo/*}"` 255 | // or `"{var=**}"`, when such a variable is expanded into a URL path on the 256 | // client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. 257 | // The server side does the reverse decoding, except "%2F" and "%2f" are left 258 | // unchanged. Such variables show up in the 259 | // [Discovery 260 | // Document](https://developers.google.com/discovery/v1/reference/apis) as 261 | // `{+var}`. 262 | // 263 | // ## Using gRPC API Service Configuration 264 | // 265 | // gRPC API Service Configuration (service config) is a configuration language 266 | // for configuring a gRPC service to become a user-facing product. The 267 | // service config is simply the YAML representation of the `google.api.Service` 268 | // proto message. 269 | // 270 | // As an alternative to annotating your proto file, you can configure gRPC 271 | // transcoding in your service config YAML files. You do this by specifying a 272 | // `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same 273 | // effect as the proto annotation. This can be particularly useful if you 274 | // have a proto that is reused in multiple services. Note that any transcoding 275 | // specified in the service config will override any matching transcoding 276 | // configuration in the proto. 277 | // 278 | // Example: 279 | // 280 | // http: 281 | // rules: 282 | // # Selects a gRPC method and applies HttpRule to it. 283 | // - selector: example.v1.Messaging.GetMessage 284 | // get: /v1/messages/{message_id}/{sub.subfield} 285 | // 286 | // ## Special notes 287 | // 288 | // When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the 289 | // proto to JSON conversion must follow the [proto3 290 | // specification](https://developers.google.com/protocol-buffers/docs/proto3#json). 291 | // 292 | // While the single segment variable follows the semantics of 293 | // [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String 294 | // Expansion, the multi segment variable **does not** follow RFC 6570 Section 295 | // 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion 296 | // does not expand special characters like `?` and `#`, which would lead 297 | // to invalid URLs. As the result, gRPC Transcoding uses a custom encoding 298 | // for multi segment variables. 299 | // 300 | // The path variables **must not** refer to any repeated or mapped field, 301 | // because client libraries are not capable of handling such variable expansion. 302 | // 303 | // The path variables **must not** capture the leading "/" character. The reason 304 | // is that the most common use case "{var}" does not capture the leading "/" 305 | // character. For consistency, all path variables must share the same behavior. 306 | // 307 | // Repeated message fields must not be mapped to URL query parameters, because 308 | // no client library can support such complicated mapping. 309 | // 310 | // If an API needs to use a JSON array for request or response body, it can map 311 | // the request or response body to a repeated field. However, some gRPC 312 | // Transcoding implementations may not support this feature. 313 | message HttpRule { 314 | // Selects a method to which this rule applies. 315 | // 316 | // Refer to [selector][google.api.DocumentationRule.selector] for syntax details. 317 | string selector = 1; 318 | 319 | // Determines the URL pattern is matched by this rules. This pattern can be 320 | // used with any of the {get|put|post|delete|patch} methods. A custom method 321 | // can be defined using the 'custom' field. 322 | oneof pattern { 323 | // Maps to HTTP GET. Used for listing and getting information about 324 | // resources. 325 | string get = 2; 326 | 327 | // Maps to HTTP PUT. Used for replacing a resource. 328 | string put = 3; 329 | 330 | // Maps to HTTP POST. Used for creating a resource or performing an action. 331 | string post = 4; 332 | 333 | // Maps to HTTP DELETE. Used for deleting a resource. 334 | string delete = 5; 335 | 336 | // Maps to HTTP PATCH. Used for updating a resource. 337 | string patch = 6; 338 | 339 | // The custom pattern is used for specifying an HTTP method that is not 340 | // included in the `pattern` field, such as HEAD, or "*" to leave the 341 | // HTTP method unspecified for this rule. The wild-card rule is useful 342 | // for services that provide content to Web (HTML) clients. 343 | CustomHttpPattern custom = 8; 344 | } 345 | 346 | // The name of the request field whose value is mapped to the HTTP request 347 | // body, or `*` for mapping all request fields not captured by the path 348 | // pattern to the HTTP body, or omitted for not having any HTTP request body. 349 | // 350 | // NOTE: the referred field must be present at the top-level of the request 351 | // message type. 352 | string body = 7; 353 | 354 | // Optional. The name of the response field whose value is mapped to the HTTP 355 | // response body. When omitted, the entire response message will be used 356 | // as the HTTP response body. 357 | // 358 | // NOTE: The referred field must be present at the top-level of the response 359 | // message type. 360 | string response_body = 12; 361 | 362 | // Additional HTTP bindings for the selector. Nested bindings must 363 | // not contain an `additional_bindings` field themselves (that is, 364 | // the nesting may only be one level deep). 365 | repeated HttpRule additional_bindings = 11; 366 | } 367 | 368 | // A custom pattern is used for defining custom HTTP verb. 369 | message CustomHttpPattern { 370 | // The name of this custom HTTP verb. 371 | string kind = 1; 372 | 373 | // The path matched by this custom verb. 374 | string path = 2; 375 | } 376 | -------------------------------------------------------------------------------- /third_party/google/api/httpbody.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/protobuf/any.proto"; 20 | 21 | option cc_enable_arenas = true; 22 | option go_package = "google.golang.org/genproto/googleapis/api/httpbody;httpbody"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "HttpBodyProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | // Message that represents an arbitrary HTTP body. It should only be used for 29 | // payload formats that can't be represented as JSON, such as raw binary or 30 | // an HTML page. 31 | // 32 | // 33 | // This message can be used both in streaming and non-streaming API methods in 34 | // the request as well as the response. 35 | // 36 | // It can be used as a top-level request field, which is convenient if one 37 | // wants to extract parameters from either the URL or HTTP template into the 38 | // request fields and also want access to the raw HTTP body. 39 | // 40 | // Example: 41 | // 42 | // message GetResourceRequest { 43 | // // A unique request id. 44 | // string request_id = 1; 45 | // 46 | // // The raw HTTP body is bound to this field. 47 | // google.api.HttpBody http_body = 2; 48 | // } 49 | // 50 | // service ResourceService { 51 | // rpc GetResource(GetResourceRequest) returns (google.api.HttpBody); 52 | // rpc UpdateResource(google.api.HttpBody) returns 53 | // (google.protobuf.Empty); 54 | // } 55 | // 56 | // Example with streaming methods: 57 | // 58 | // service CaldavService { 59 | // rpc GetCalendar(stream google.api.HttpBody) 60 | // returns (stream google.api.HttpBody); 61 | // rpc UpdateCalendar(stream google.api.HttpBody) 62 | // returns (stream google.api.HttpBody); 63 | // } 64 | // 65 | // Use of this type only changes how the request and response bodies are 66 | // handled, all other features will continue to work unchanged. 67 | message HttpBody { 68 | // The HTTP Content-Type header value specifying the content type of the body. 69 | string content_type = 1; 70 | 71 | // The HTTP request/response body as raw binary. 72 | bytes data = 2; 73 | 74 | // Application specific response metadata. Must be set in the first response 75 | // for streaming APIs. 76 | repeated google.protobuf.Any extensions = 3; 77 | } 78 | -------------------------------------------------------------------------------- /third_party/google/api/resource.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/protobuf/descriptor.proto"; 20 | 21 | option cc_enable_arenas = true; 22 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "ResourceProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | extend google.protobuf.FieldOptions { 29 | // An annotation that describes a resource reference, see 30 | // [ResourceReference][]. 31 | google.api.ResourceReference resource_reference = 1055; 32 | } 33 | 34 | extend google.protobuf.FileOptions { 35 | // An annotation that describes a resource definition without a corresponding 36 | // message; see [ResourceDescriptor][]. 37 | repeated google.api.ResourceDescriptor resource_definition = 1053; 38 | } 39 | 40 | extend google.protobuf.MessageOptions { 41 | // An annotation that describes a resource definition, see 42 | // [ResourceDescriptor][]. 43 | google.api.ResourceDescriptor resource = 1053; 44 | } 45 | 46 | // A simple descriptor of a resource type. 47 | // 48 | // ResourceDescriptor annotates a resource message (either by means of a 49 | // protobuf annotation or use in the service config), and associates the 50 | // resource's schema, the resource type, and the pattern of the resource name. 51 | // 52 | // Example: 53 | // 54 | // message Topic { 55 | // // Indicates this message defines a resource schema. 56 | // // Declares the resource type in the format of {service}/{kind}. 57 | // // For Kubernetes resources, the format is {api group}/{kind}. 58 | // option (google.api.resource) = { 59 | // type: "pubsub.googleapis.com/Topic" 60 | // pattern: "projects/{project}/topics/{topic}" 61 | // }; 62 | // } 63 | // 64 | // The ResourceDescriptor Yaml config will look like: 65 | // 66 | // resources: 67 | // - type: "pubsub.googleapis.com/Topic" 68 | // pattern: "projects/{project}/topics/{topic}" 69 | // 70 | // Sometimes, resources have multiple patterns, typically because they can 71 | // live under multiple parents. 72 | // 73 | // Example: 74 | // 75 | // message LogEntry { 76 | // option (google.api.resource) = { 77 | // type: "logging.googleapis.com/LogEntry" 78 | // pattern: "projects/{project}/logs/{log}" 79 | // pattern: "folders/{folder}/logs/{log}" 80 | // pattern: "organizations/{organization}/logs/{log}" 81 | // pattern: "billingAccounts/{billing_account}/logs/{log}" 82 | // }; 83 | // } 84 | // 85 | // The ResourceDescriptor Yaml config will look like: 86 | // 87 | // resources: 88 | // - type: 'logging.googleapis.com/LogEntry' 89 | // pattern: "projects/{project}/logs/{log}" 90 | // pattern: "folders/{folder}/logs/{log}" 91 | // pattern: "organizations/{organization}/logs/{log}" 92 | // pattern: "billingAccounts/{billing_account}/logs/{log}" 93 | message ResourceDescriptor { 94 | // A description of the historical or future-looking state of the 95 | // resource pattern. 96 | enum History { 97 | // The "unset" value. 98 | HISTORY_UNSPECIFIED = 0; 99 | 100 | // The resource originally had one pattern and launched as such, and 101 | // additional patterns were added later. 102 | ORIGINALLY_SINGLE_PATTERN = 1; 103 | 104 | // The resource has one pattern, but the API owner expects to add more 105 | // later. (This is the inverse of ORIGINALLY_SINGLE_PATTERN, and prevents 106 | // that from being necessary once there are multiple patterns.) 107 | FUTURE_MULTI_PATTERN = 2; 108 | } 109 | 110 | // A flag representing a specific style that a resource claims to conform to. 111 | enum Style { 112 | // The unspecified value. Do not use. 113 | STYLE_UNSPECIFIED = 0; 114 | 115 | // This resource is intended to be "declarative-friendly". 116 | // 117 | // Declarative-friendly resources must be more strictly consistent, and 118 | // setting this to true communicates to tools that this resource should 119 | // adhere to declarative-friendly expectations. 120 | // 121 | // Note: This is used by the API linter (linter.aip.dev) to enable 122 | // additional checks. 123 | DECLARATIVE_FRIENDLY = 1; 124 | } 125 | 126 | // The resource type. It must be in the format of 127 | // {service_name}/{resource_type_kind}. The `resource_type_kind` must be 128 | // singular and must not include version numbers. 129 | // 130 | // Example: `storage.googleapis.com/Bucket` 131 | // 132 | // The value of the resource_type_kind must follow the regular expression 133 | // /[A-Za-z][a-zA-Z0-9]+/. It should start with an upper case character and 134 | // should use PascalCase (UpperCamelCase). The maximum number of 135 | // characters allowed for the `resource_type_kind` is 100. 136 | string type = 1; 137 | 138 | // Optional. The relative resource name pattern associated with this resource 139 | // type. The DNS prefix of the full resource name shouldn't be specified here. 140 | // 141 | // The path pattern must follow the syntax, which aligns with HTTP binding 142 | // syntax: 143 | // 144 | // Template = Segment { "/" Segment } ; 145 | // Segment = LITERAL | Variable ; 146 | // Variable = "{" LITERAL "}" ; 147 | // 148 | // Examples: 149 | // 150 | // - "projects/{project}/topics/{topic}" 151 | // - "projects/{project}/knowledgeBases/{knowledge_base}" 152 | // 153 | // The components in braces correspond to the IDs for each resource in the 154 | // hierarchy. It is expected that, if multiple patterns are provided, 155 | // the same component name (e.g. "project") refers to IDs of the same 156 | // type of resource. 157 | repeated string pattern = 2; 158 | 159 | // Optional. The field on the resource that designates the resource name 160 | // field. If omitted, this is assumed to be "name". 161 | string name_field = 3; 162 | 163 | // Optional. The historical or future-looking state of the resource pattern. 164 | // 165 | // Example: 166 | // 167 | // // The InspectTemplate message originally only supported resource 168 | // // names with organization, and project was added later. 169 | // message InspectTemplate { 170 | // option (google.api.resource) = { 171 | // type: "dlp.googleapis.com/InspectTemplate" 172 | // pattern: 173 | // "organizations/{organization}/inspectTemplates/{inspect_template}" 174 | // pattern: "projects/{project}/inspectTemplates/{inspect_template}" 175 | // history: ORIGINALLY_SINGLE_PATTERN 176 | // }; 177 | // } 178 | History history = 4; 179 | 180 | // The plural name used in the resource name and permission names, such as 181 | // 'projects' for the resource name of 'projects/{project}' and the permission 182 | // name of 'cloudresourcemanager.googleapis.com/projects.get'. It is the same 183 | // concept of the `plural` field in k8s CRD spec 184 | // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ 185 | // 186 | // Note: The plural form is required even for singleton resources. See 187 | // https://aip.dev/156 188 | string plural = 5; 189 | 190 | // The same concept of the `singular` field in k8s CRD spec 191 | // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ 192 | // Such as "project" for the `resourcemanager.googleapis.com/Project` type. 193 | string singular = 6; 194 | 195 | // Style flag(s) for this resource. 196 | // These indicate that a resource is expected to conform to a given 197 | // style. See the specific style flags for additional information. 198 | repeated Style style = 10; 199 | } 200 | 201 | // Defines a proto annotation that describes a string field that refers to 202 | // an API resource. 203 | message ResourceReference { 204 | // The resource type that the annotated field references. 205 | // 206 | // Example: 207 | // 208 | // message Subscription { 209 | // string topic = 2 [(google.api.resource_reference) = { 210 | // type: "pubsub.googleapis.com/Topic" 211 | // }]; 212 | // } 213 | // 214 | // Occasionally, a field may reference an arbitrary resource. In this case, 215 | // APIs use the special value * in their resource reference. 216 | // 217 | // Example: 218 | // 219 | // message GetIamPolicyRequest { 220 | // string resource = 2 [(google.api.resource_reference) = { 221 | // type: "*" 222 | // }]; 223 | // } 224 | string type = 1; 225 | 226 | // The resource type of a child collection that the annotated field 227 | // references. This is useful for annotating the `parent` field that 228 | // doesn't have a fixed resource type. 229 | // 230 | // Example: 231 | // 232 | // message ListLogEntriesRequest { 233 | // string parent = 1 [(google.api.resource_reference) = { 234 | // child_type: "logging.googleapis.com/LogEntry" 235 | // }; 236 | // } 237 | string child_type = 2; 238 | } 239 | -------------------------------------------------------------------------------- /third_party/google/api/routing.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/protobuf/descriptor.proto"; 20 | 21 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 22 | option java_multiple_files = true; 23 | option java_outer_classname = "RoutingProto"; 24 | option java_package = "com.google.api"; 25 | option objc_class_prefix = "GAPI"; 26 | 27 | extend google.protobuf.MethodOptions { 28 | // See RoutingRule. 29 | google.api.RoutingRule routing = 72295729; 30 | } 31 | 32 | // Specifies the routing information that should be sent along with the request 33 | // in the form of routing header. 34 | // **NOTE:** All service configuration rules follow the "last one wins" order. 35 | // 36 | // The examples below will apply to an RPC which has the following request type: 37 | // 38 | // Message Definition: 39 | // 40 | // message Request { 41 | // // The name of the Table 42 | // // Values can be of the following formats: 43 | // // - `projects//tables/` 44 | // // - `projects//instances//tables/
` 45 | // // - `region//zones//tables/
` 46 | // string table_name = 1; 47 | // 48 | // // This value specifies routing for replication. 49 | // // It can be in the following formats: 50 | // // - `profiles/` 51 | // // - a legacy `profile_id` that can be any string 52 | // string app_profile_id = 2; 53 | // } 54 | // 55 | // Example message: 56 | // 57 | // { 58 | // table_name: projects/proj_foo/instances/instance_bar/table/table_baz, 59 | // app_profile_id: profiles/prof_qux 60 | // } 61 | // 62 | // The routing header consists of one or multiple key-value pairs. Every key 63 | // and value must be percent-encoded, and joined together in the format of 64 | // `key1=value1&key2=value2`. 65 | // In the examples below I am skipping the percent-encoding for readablity. 66 | // 67 | // Example 1 68 | // 69 | // Extracting a field from the request to put into the routing header 70 | // unchanged, with the key equal to the field name. 71 | // 72 | // annotation: 73 | // 74 | // option (google.api.routing) = { 75 | // // Take the `app_profile_id`. 76 | // routing_parameters { 77 | // field: "app_profile_id" 78 | // } 79 | // }; 80 | // 81 | // result: 82 | // 83 | // x-goog-request-params: app_profile_id=profiles/prof_qux 84 | // 85 | // Example 2 86 | // 87 | // Extracting a field from the request to put into the routing header 88 | // unchanged, with the key different from the field name. 89 | // 90 | // annotation: 91 | // 92 | // option (google.api.routing) = { 93 | // // Take the `app_profile_id`, but name it `routing_id` in the header. 94 | // routing_parameters { 95 | // field: "app_profile_id" 96 | // path_template: "{routing_id=**}" 97 | // } 98 | // }; 99 | // 100 | // result: 101 | // 102 | // x-goog-request-params: routing_id=profiles/prof_qux 103 | // 104 | // Example 3 105 | // 106 | // Extracting a field from the request to put into the routing 107 | // header, while matching a path template syntax on the field's value. 108 | // 109 | // NB: it is more useful to send nothing than to send garbage for the purpose 110 | // of dynamic routing, since garbage pollutes cache. Thus the matching. 111 | // 112 | // Sub-example 3a 113 | // 114 | // The field matches the template. 115 | // 116 | // annotation: 117 | // 118 | // option (google.api.routing) = { 119 | // // Take the `table_name`, if it's well-formed (with project-based 120 | // // syntax). 121 | // routing_parameters { 122 | // field: "table_name" 123 | // path_template: "{table_name=projects/*/instances/*/**}" 124 | // } 125 | // }; 126 | // 127 | // result: 128 | // 129 | // x-goog-request-params: 130 | // table_name=projects/proj_foo/instances/instance_bar/table/table_baz 131 | // 132 | // Sub-example 3b 133 | // 134 | // The field does not match the template. 135 | // 136 | // annotation: 137 | // 138 | // option (google.api.routing) = { 139 | // // Take the `table_name`, if it's well-formed (with region-based 140 | // // syntax). 141 | // routing_parameters { 142 | // field: "table_name" 143 | // path_template: "{table_name=regions/*/zones/*/**}" 144 | // } 145 | // }; 146 | // 147 | // result: 148 | // 149 | // 150 | // 151 | // Sub-example 3c 152 | // 153 | // Multiple alternative conflictingly named path templates are 154 | // specified. The one that matches is used to construct the header. 155 | // 156 | // annotation: 157 | // 158 | // option (google.api.routing) = { 159 | // // Take the `table_name`, if it's well-formed, whether 160 | // // using the region- or projects-based syntax. 161 | // 162 | // routing_parameters { 163 | // field: "table_name" 164 | // path_template: "{table_name=regions/*/zones/*/**}" 165 | // } 166 | // routing_parameters { 167 | // field: "table_name" 168 | // path_template: "{table_name=projects/*/instances/*/**}" 169 | // } 170 | // }; 171 | // 172 | // result: 173 | // 174 | // x-goog-request-params: 175 | // table_name=projects/proj_foo/instances/instance_bar/table/table_baz 176 | // 177 | // Example 4 178 | // 179 | // Extracting a single routing header key-value pair by matching a 180 | // template syntax on (a part of) a single request field. 181 | // 182 | // annotation: 183 | // 184 | // option (google.api.routing) = { 185 | // // Take just the project id from the `table_name` field. 186 | // routing_parameters { 187 | // field: "table_name" 188 | // path_template: "{routing_id=projects/*}/**" 189 | // } 190 | // }; 191 | // 192 | // result: 193 | // 194 | // x-goog-request-params: routing_id=projects/proj_foo 195 | // 196 | // Example 5 197 | // 198 | // Extracting a single routing header key-value pair by matching 199 | // several conflictingly named path templates on (parts of) a single request 200 | // field. The last template to match "wins" the conflict. 201 | // 202 | // annotation: 203 | // 204 | // option (google.api.routing) = { 205 | // // If the `table_name` does not have instances information, 206 | // // take just the project id for routing. 207 | // // Otherwise take project + instance. 208 | // 209 | // routing_parameters { 210 | // field: "table_name" 211 | // path_template: "{routing_id=projects/*}/**" 212 | // } 213 | // routing_parameters { 214 | // field: "table_name" 215 | // path_template: "{routing_id=projects/*/instances/*}/**" 216 | // } 217 | // }; 218 | // 219 | // result: 220 | // 221 | // x-goog-request-params: 222 | // routing_id=projects/proj_foo/instances/instance_bar 223 | // 224 | // Example 6 225 | // 226 | // Extracting multiple routing header key-value pairs by matching 227 | // several non-conflicting path templates on (parts of) a single request field. 228 | // 229 | // Sub-example 6a 230 | // 231 | // Make the templates strict, so that if the `table_name` does not 232 | // have an instance information, nothing is sent. 233 | // 234 | // annotation: 235 | // 236 | // option (google.api.routing) = { 237 | // // The routing code needs two keys instead of one composite 238 | // // but works only for the tables with the "project-instance" name 239 | // // syntax. 240 | // 241 | // routing_parameters { 242 | // field: "table_name" 243 | // path_template: "{project_id=projects/*}/instances/*/**" 244 | // } 245 | // routing_parameters { 246 | // field: "table_name" 247 | // path_template: "projects/*/{instance_id=instances/*}/**" 248 | // } 249 | // }; 250 | // 251 | // result: 252 | // 253 | // x-goog-request-params: 254 | // project_id=projects/proj_foo&instance_id=instances/instance_bar 255 | // 256 | // Sub-example 6b 257 | // 258 | // Make the templates loose, so that if the `table_name` does not 259 | // have an instance information, just the project id part is sent. 260 | // 261 | // annotation: 262 | // 263 | // option (google.api.routing) = { 264 | // // The routing code wants two keys instead of one composite 265 | // // but will work with just the `project_id` for tables without 266 | // // an instance in the `table_name`. 267 | // 268 | // routing_parameters { 269 | // field: "table_name" 270 | // path_template: "{project_id=projects/*}/**" 271 | // } 272 | // routing_parameters { 273 | // field: "table_name" 274 | // path_template: "projects/*/{instance_id=instances/*}/**" 275 | // } 276 | // }; 277 | // 278 | // result (is the same as 6a for our example message because it has the instance 279 | // information): 280 | // 281 | // x-goog-request-params: 282 | // project_id=projects/proj_foo&instance_id=instances/instance_bar 283 | // 284 | // Example 7 285 | // 286 | // Extracting multiple routing header key-value pairs by matching 287 | // several path templates on multiple request fields. 288 | // 289 | // NB: note that here there is no way to specify sending nothing if one of the 290 | // fields does not match its template. E.g. if the `table_name` is in the wrong 291 | // format, the `project_id` will not be sent, but the `routing_id` will be. 292 | // The backend routing code has to be aware of that and be prepared to not 293 | // receive a full complement of keys if it expects multiple. 294 | // 295 | // annotation: 296 | // 297 | // option (google.api.routing) = { 298 | // // The routing needs both `project_id` and `routing_id` 299 | // // (from the `app_profile_id` field) for routing. 300 | // 301 | // routing_parameters { 302 | // field: "table_name" 303 | // path_template: "{project_id=projects/*}/**" 304 | // } 305 | // routing_parameters { 306 | // field: "app_profile_id" 307 | // path_template: "{routing_id=**}" 308 | // } 309 | // }; 310 | // 311 | // result: 312 | // 313 | // x-goog-request-params: 314 | // project_id=projects/proj_foo&routing_id=profiles/prof_qux 315 | // 316 | // Example 8 317 | // 318 | // Extracting a single routing header key-value pair by matching 319 | // several conflictingly named path templates on several request fields. The 320 | // last template to match "wins" the conflict. 321 | // 322 | // annotation: 323 | // 324 | // option (google.api.routing) = { 325 | // // The `routing_id` can be a project id or a region id depending on 326 | // // the table name format, but only if the `app_profile_id` is not set. 327 | // // If `app_profile_id` is set it should be used instead. 328 | // 329 | // routing_parameters { 330 | // field: "table_name" 331 | // path_template: "{routing_id=projects/*}/**" 332 | // } 333 | // routing_parameters { 334 | // field: "table_name" 335 | // path_template: "{routing_id=regions/*}/**" 336 | // } 337 | // routing_parameters { 338 | // field: "app_profile_id" 339 | // path_template: "{routing_id=**}" 340 | // } 341 | // }; 342 | // 343 | // result: 344 | // 345 | // x-goog-request-params: routing_id=profiles/prof_qux 346 | // 347 | // Example 9 348 | // 349 | // Bringing it all together. 350 | // 351 | // annotation: 352 | // 353 | // option (google.api.routing) = { 354 | // // For routing both `table_location` and a `routing_id` are needed. 355 | // // 356 | // // table_location can be either an instance id or a region+zone id. 357 | // // 358 | // // For `routing_id`, take the value of `app_profile_id` 359 | // // - If it's in the format `profiles/`, send 360 | // // just the `` part. 361 | // // - If it's any other literal, send it as is. 362 | // // If the `app_profile_id` is empty, and the `table_name` starts with 363 | // // the project_id, send that instead. 364 | // 365 | // routing_parameters { 366 | // field: "table_name" 367 | // path_template: "projects/*/{table_location=instances/*}/tables/*" 368 | // } 369 | // routing_parameters { 370 | // field: "table_name" 371 | // path_template: "{table_location=regions/*/zones/*}/tables/*" 372 | // } 373 | // routing_parameters { 374 | // field: "table_name" 375 | // path_template: "{routing_id=projects/*}/**" 376 | // } 377 | // routing_parameters { 378 | // field: "app_profile_id" 379 | // path_template: "{routing_id=**}" 380 | // } 381 | // routing_parameters { 382 | // field: "app_profile_id" 383 | // path_template: "profiles/{routing_id=*}" 384 | // } 385 | // }; 386 | // 387 | // result: 388 | // 389 | // x-goog-request-params: 390 | // table_location=instances/instance_bar&routing_id=prof_qux 391 | message RoutingRule { 392 | // A collection of Routing Parameter specifications. 393 | // **NOTE:** If multiple Routing Parameters describe the same key 394 | // (via the `path_template` field or via the `field` field when 395 | // `path_template` is not provided), "last one wins" rule 396 | // determines which Parameter gets used. 397 | // See the examples for more details. 398 | repeated RoutingParameter routing_parameters = 2; 399 | } 400 | 401 | // A projection from an input message to the GRPC or REST header. 402 | message RoutingParameter { 403 | // A request field to extract the header key-value pair from. 404 | string field = 1; 405 | 406 | // A pattern matching the key-value field. Optional. 407 | // If not specified, the whole field specified in the `field` field will be 408 | // taken as value, and its name used as key. If specified, it MUST contain 409 | // exactly one named segment (along with any number of unnamed segments) The 410 | // pattern will be matched over the field specified in the `field` field, then 411 | // if the match is successful: 412 | // - the name of the single named segment will be used as a header name, 413 | // - the match value of the segment will be used as a header value; 414 | // if the match is NOT successful, nothing will be sent. 415 | // 416 | // Example: 417 | // 418 | // -- This is a field in the request message 419 | // | that the header value will be extracted from. 420 | // | 421 | // | -- This is the key name in the 422 | // | | routing header. 423 | // V | 424 | // field: "table_name" v 425 | // path_template: "projects/*/{table_location=instances/*}/tables/*" 426 | // ^ ^ 427 | // | | 428 | // In the {} brackets is the pattern that -- | 429 | // specifies what to extract from the | 430 | // field as a value to be sent. | 431 | // | 432 | // The string in the field must match the whole pattern -- 433 | // before brackets, inside brackets, after brackets. 434 | // 435 | // When looking at this specific example, we can see that: 436 | // - A key-value pair with the key `table_location` 437 | // and the value matching `instances/*` should be added 438 | // to the x-goog-request-params routing header. 439 | // - The value is extracted from the request message's `table_name` field 440 | // if it matches the full pattern specified: 441 | // `projects/*/instances/*/tables/*`. 442 | // 443 | // **NB:** If the `path_template` field is not provided, the key name is 444 | // equal to the field name, and the whole field should be sent as a value. 445 | // This makes the pattern for the field and the value functionally equivalent 446 | // to `**`, and the configuration 447 | // 448 | // { 449 | // field: "table_name" 450 | // } 451 | // 452 | // is a functionally equivalent shorthand to: 453 | // 454 | // { 455 | // field: "table_name" 456 | // path_template: "{table_name=**}" 457 | // } 458 | // 459 | // See Example 1 for more details. 460 | string path_template = 2; 461 | } 462 | -------------------------------------------------------------------------------- /third_party/google/protobuf/any.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option go_package = "google.golang.org/protobuf/types/known/anypb"; 37 | option java_package = "com.google.protobuf"; 38 | option java_outer_classname = "AnyProto"; 39 | option java_multiple_files = true; 40 | option objc_class_prefix = "GPB"; 41 | 42 | // `Any` contains an arbitrary serialized protocol buffer message along with a 43 | // URL that describes the type of the serialized message. 44 | // 45 | // Protobuf library provides support to pack/unpack Any values in the form 46 | // of utility functions or additional generated methods of the Any type. 47 | // 48 | // Example 1: Pack and unpack a message in C++. 49 | // 50 | // Foo foo = ...; 51 | // Any any; 52 | // any.PackFrom(foo); 53 | // ... 54 | // if (any.UnpackTo(&foo)) { 55 | // ... 56 | // } 57 | // 58 | // Example 2: Pack and unpack a message in Java. 59 | // 60 | // Foo foo = ...; 61 | // Any any = Any.pack(foo); 62 | // ... 63 | // if (any.is(Foo.class)) { 64 | // foo = any.unpack(Foo.class); 65 | // } 66 | // 67 | // Example 3: Pack and unpack a message in Python. 68 | // 69 | // foo = Foo(...) 70 | // any = Any() 71 | // any.Pack(foo) 72 | // ... 73 | // if any.Is(Foo.DESCRIPTOR): 74 | // any.Unpack(foo) 75 | // ... 76 | // 77 | // Example 4: Pack and unpack a message in Go 78 | // 79 | // foo := &pb.Foo{...} 80 | // any, err := anypb.New(foo) 81 | // if err != nil { 82 | // ... 83 | // } 84 | // ... 85 | // foo := &pb.Foo{} 86 | // if err := any.UnmarshalTo(foo); err != nil { 87 | // ... 88 | // } 89 | // 90 | // The pack methods provided by protobuf library will by default use 91 | // 'type.googleapis.com/full.type.name' as the type URL and the unpack 92 | // methods only use the fully qualified type name after the last '/' 93 | // in the type URL, for example "foo.bar.com/x/y.z" will yield type 94 | // name "y.z". 95 | // 96 | // 97 | // JSON 98 | // ==== 99 | // The JSON representation of an `Any` value uses the regular 100 | // representation of the deserialized, embedded message, with an 101 | // additional field `@type` which contains the type URL. Example: 102 | // 103 | // package google.profile; 104 | // message Person { 105 | // string first_name = 1; 106 | // string last_name = 2; 107 | // } 108 | // 109 | // { 110 | // "@type": "type.googleapis.com/google.profile.Person", 111 | // "firstName": , 112 | // "lastName": 113 | // } 114 | // 115 | // If the embedded message type is well-known and has a custom JSON 116 | // representation, that representation will be embedded adding a field 117 | // `value` which holds the custom JSON in addition to the `@type` 118 | // field. Example (for message [google.protobuf.Duration][]): 119 | // 120 | // { 121 | // "@type": "type.googleapis.com/google.protobuf.Duration", 122 | // "value": "1.212s" 123 | // } 124 | // 125 | message Any { 126 | // A URL/resource name that uniquely identifies the type of the serialized 127 | // protocol buffer message. This string must contain at least 128 | // one "/" character. The last segment of the URL's path must represent 129 | // the fully qualified name of the type (as in 130 | // `path/google.protobuf.Duration`). The name should be in a canonical form 131 | // (e.g., leading "." is not accepted). 132 | // 133 | // In practice, teams usually precompile into the binary all types that they 134 | // expect it to use in the context of Any. However, for URLs which use the 135 | // scheme `http`, `https`, or no scheme, one can optionally set up a type 136 | // server that maps type URLs to message definitions as follows: 137 | // 138 | // * If no scheme is provided, `https` is assumed. 139 | // * An HTTP GET on the URL must yield a [google.protobuf.Type][] 140 | // value in binary format, or produce an error. 141 | // * Applications are allowed to cache lookup results based on the 142 | // URL, or have them precompiled into a binary to avoid any 143 | // lookup. Therefore, binary compatibility needs to be preserved 144 | // on changes to types. (Use versioned type names to manage 145 | // breaking changes.) 146 | // 147 | // Note: this functionality is not currently available in the official 148 | // protobuf release, and it is not used for type URLs beginning with 149 | // type.googleapis.com. 150 | // 151 | // Schemes other than `http`, `https` (or the empty scheme) might be 152 | // used with implementation specific semantics. 153 | // 154 | string type_url = 1; 155 | 156 | // Must be a valid serialized protocol buffer of the above specified type. 157 | bytes value = 2; 158 | } 159 | -------------------------------------------------------------------------------- /third_party/google/protobuf/api.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | import "google/protobuf/source_context.proto"; 36 | import "google/protobuf/type.proto"; 37 | 38 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 39 | option java_package = "com.google.protobuf"; 40 | option java_outer_classname = "ApiProto"; 41 | option java_multiple_files = true; 42 | option objc_class_prefix = "GPB"; 43 | option go_package = "google.golang.org/protobuf/types/known/apipb"; 44 | 45 | // Api is a light-weight descriptor for an API Interface. 46 | // 47 | // Interfaces are also described as "protocol buffer services" in some contexts, 48 | // such as by the "service" keyword in a .proto file, but they are different 49 | // from API Services, which represent a concrete implementation of an interface 50 | // as opposed to simply a description of methods and bindings. They are also 51 | // sometimes simply referred to as "APIs" in other contexts, such as the name of 52 | // this message itself. See https://cloud.google.com/apis/design/glossary for 53 | // detailed terminology. 54 | message Api { 55 | // The fully qualified name of this interface, including package name 56 | // followed by the interface's simple name. 57 | string name = 1; 58 | 59 | // The methods of this interface, in unspecified order. 60 | repeated Method methods = 2; 61 | 62 | // Any metadata attached to the interface. 63 | repeated Option options = 3; 64 | 65 | // A version string for this interface. If specified, must have the form 66 | // `major-version.minor-version`, as in `1.10`. If the minor version is 67 | // omitted, it defaults to zero. If the entire version field is empty, the 68 | // major version is derived from the package name, as outlined below. If the 69 | // field is not empty, the version in the package name will be verified to be 70 | // consistent with what is provided here. 71 | // 72 | // The versioning schema uses [semantic 73 | // versioning](http://semver.org) where the major version number 74 | // indicates a breaking change and the minor version an additive, 75 | // non-breaking change. Both version numbers are signals to users 76 | // what to expect from different versions, and should be carefully 77 | // chosen based on the product plan. 78 | // 79 | // The major version is also reflected in the package name of the 80 | // interface, which must end in `v`, as in 81 | // `google.feature.v1`. For major versions 0 and 1, the suffix can 82 | // be omitted. Zero major versions must only be used for 83 | // experimental, non-GA interfaces. 84 | // 85 | // 86 | string version = 4; 87 | 88 | // Source context for the protocol buffer service represented by this 89 | // message. 90 | SourceContext source_context = 5; 91 | 92 | // Included interfaces. See [Mixin][]. 93 | repeated Mixin mixins = 6; 94 | 95 | // The source syntax of the service. 96 | Syntax syntax = 7; 97 | } 98 | 99 | // Method represents a method of an API interface. 100 | message Method { 101 | // The simple name of this method. 102 | string name = 1; 103 | 104 | // A URL of the input message type. 105 | string request_type_url = 2; 106 | 107 | // If true, the request is streamed. 108 | bool request_streaming = 3; 109 | 110 | // The URL of the output message type. 111 | string response_type_url = 4; 112 | 113 | // If true, the response is streamed. 114 | bool response_streaming = 5; 115 | 116 | // Any metadata attached to the method. 117 | repeated Option options = 6; 118 | 119 | // The source syntax of this method. 120 | Syntax syntax = 7; 121 | } 122 | 123 | // Declares an API Interface to be included in this interface. The including 124 | // interface must redeclare all the methods from the included interface, but 125 | // documentation and options are inherited as follows: 126 | // 127 | // - If after comment and whitespace stripping, the documentation 128 | // string of the redeclared method is empty, it will be inherited 129 | // from the original method. 130 | // 131 | // - Each annotation belonging to the service config (http, 132 | // visibility) which is not set in the redeclared method will be 133 | // inherited. 134 | // 135 | // - If an http annotation is inherited, the path pattern will be 136 | // modified as follows. Any version prefix will be replaced by the 137 | // version of the including interface plus the [root][] path if 138 | // specified. 139 | // 140 | // Example of a simple mixin: 141 | // 142 | // package google.acl.v1; 143 | // service AccessControl { 144 | // // Get the underlying ACL object. 145 | // rpc GetAcl(GetAclRequest) returns (Acl) { 146 | // option (google.api.http).get = "/v1/{resource=**}:getAcl"; 147 | // } 148 | // } 149 | // 150 | // package google.storage.v2; 151 | // service Storage { 152 | // rpc GetAcl(GetAclRequest) returns (Acl); 153 | // 154 | // // Get a data record. 155 | // rpc GetData(GetDataRequest) returns (Data) { 156 | // option (google.api.http).get = "/v2/{resource=**}"; 157 | // } 158 | // } 159 | // 160 | // Example of a mixin configuration: 161 | // 162 | // apis: 163 | // - name: google.storage.v2.Storage 164 | // mixins: 165 | // - name: google.acl.v1.AccessControl 166 | // 167 | // The mixin construct implies that all methods in `AccessControl` are 168 | // also declared with same name and request/response types in 169 | // `Storage`. A documentation generator or annotation processor will 170 | // see the effective `Storage.GetAcl` method after inheriting 171 | // documentation and annotations as follows: 172 | // 173 | // service Storage { 174 | // // Get the underlying ACL object. 175 | // rpc GetAcl(GetAclRequest) returns (Acl) { 176 | // option (google.api.http).get = "/v2/{resource=**}:getAcl"; 177 | // } 178 | // ... 179 | // } 180 | // 181 | // Note how the version in the path pattern changed from `v1` to `v2`. 182 | // 183 | // If the `root` field in the mixin is specified, it should be a 184 | // relative path under which inherited HTTP paths are placed. Example: 185 | // 186 | // apis: 187 | // - name: google.storage.v2.Storage 188 | // mixins: 189 | // - name: google.acl.v1.AccessControl 190 | // root: acls 191 | // 192 | // This implies the following inherited HTTP annotation: 193 | // 194 | // service Storage { 195 | // // Get the underlying ACL object. 196 | // rpc GetAcl(GetAclRequest) returns (Acl) { 197 | // option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; 198 | // } 199 | // ... 200 | // } 201 | message Mixin { 202 | // The fully qualified name of the interface which is included. 203 | string name = 1; 204 | 205 | // If non-empty specifies a path under which inherited HTTP paths 206 | // are rooted. 207 | string root = 2; 208 | } 209 | -------------------------------------------------------------------------------- /third_party/google/protobuf/compiler/plugin.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // 33 | // WARNING: The plugin interface is currently EXPERIMENTAL and is subject to 34 | // change. 35 | // 36 | // protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is 37 | // just a program that reads a CodeGeneratorRequest from stdin and writes a 38 | // CodeGeneratorResponse to stdout. 39 | // 40 | // Plugins written using C++ can use google/protobuf/compiler/plugin.h instead 41 | // of dealing with the raw protocol defined here. 42 | // 43 | // A plugin executable needs only to be placed somewhere in the path. The 44 | // plugin should be named "protoc-gen-$NAME", and will then be used when the 45 | // flag "--${NAME}_out" is passed to protoc. 46 | 47 | syntax = "proto2"; 48 | 49 | package google.protobuf.compiler; 50 | option java_package = "com.google.protobuf.compiler"; 51 | option java_outer_classname = "PluginProtos"; 52 | 53 | option go_package = "google.golang.org/protobuf/types/pluginpb"; 54 | 55 | import "google/protobuf/descriptor.proto"; 56 | 57 | // The version number of protocol compiler. 58 | message Version { 59 | optional int32 major = 1; 60 | optional int32 minor = 2; 61 | optional int32 patch = 3; 62 | // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should 63 | // be empty for mainline stable releases. 64 | optional string suffix = 4; 65 | } 66 | 67 | // An encoded CodeGeneratorRequest is written to the plugin's stdin. 68 | message CodeGeneratorRequest { 69 | // The .proto files that were explicitly listed on the command-line. The 70 | // code generator should generate code only for these files. Each file's 71 | // descriptor will be included in proto_file, below. 72 | repeated string file_to_generate = 1; 73 | 74 | // The generator parameter passed on the command-line. 75 | optional string parameter = 2; 76 | 77 | // FileDescriptorProtos for all files in files_to_generate and everything 78 | // they import. The files will appear in topological order, so each file 79 | // appears before any file that imports it. 80 | // 81 | // protoc guarantees that all proto_files will be written after 82 | // the fields above, even though this is not technically guaranteed by the 83 | // protobuf wire format. This theoretically could allow a plugin to stream 84 | // in the FileDescriptorProtos and handle them one by one rather than read 85 | // the entire set into memory at once. However, as of this writing, this 86 | // is not similarly optimized on protoc's end -- it will store all fields in 87 | // memory at once before sending them to the plugin. 88 | // 89 | // Type names of fields and extensions in the FileDescriptorProto are always 90 | // fully qualified. 91 | repeated FileDescriptorProto proto_file = 15; 92 | 93 | // The version number of protocol compiler. 94 | optional Version compiler_version = 3; 95 | 96 | } 97 | 98 | // The plugin writes an encoded CodeGeneratorResponse to stdout. 99 | message CodeGeneratorResponse { 100 | // Error message. If non-empty, code generation failed. The plugin process 101 | // should exit with status code zero even if it reports an error in this way. 102 | // 103 | // This should be used to indicate errors in .proto files which prevent the 104 | // code generator from generating correct code. Errors which indicate a 105 | // problem in protoc itself -- such as the input CodeGeneratorRequest being 106 | // unparseable -- should be reported by writing a message to stderr and 107 | // exiting with a non-zero status code. 108 | optional string error = 1; 109 | 110 | // A bitmask of supported features that the code generator supports. 111 | // This is a bitwise "or" of values from the Feature enum. 112 | optional uint64 supported_features = 2; 113 | 114 | // Sync with code_generator.h. 115 | enum Feature { 116 | FEATURE_NONE = 0; 117 | FEATURE_PROTO3_OPTIONAL = 1; 118 | } 119 | 120 | // Represents a single generated file. 121 | message File { 122 | // The file name, relative to the output directory. The name must not 123 | // contain "." or ".." components and must be relative, not be absolute (so, 124 | // the file cannot lie outside the output directory). "/" must be used as 125 | // the path separator, not "\". 126 | // 127 | // If the name is omitted, the content will be appended to the previous 128 | // file. This allows the generator to break large files into small chunks, 129 | // and allows the generated text to be streamed back to protoc so that large 130 | // files need not reside completely in memory at one time. Note that as of 131 | // this writing protoc does not optimize for this -- it will read the entire 132 | // CodeGeneratorResponse before writing files to disk. 133 | optional string name = 1; 134 | 135 | // If non-empty, indicates that the named file should already exist, and the 136 | // content here is to be inserted into that file at a defined insertion 137 | // point. This feature allows a code generator to extend the output 138 | // produced by another code generator. The original generator may provide 139 | // insertion points by placing special annotations in the file that look 140 | // like: 141 | // @@protoc_insertion_point(NAME) 142 | // The annotation can have arbitrary text before and after it on the line, 143 | // which allows it to be placed in a comment. NAME should be replaced with 144 | // an identifier naming the point -- this is what other generators will use 145 | // as the insertion_point. Code inserted at this point will be placed 146 | // immediately above the line containing the insertion point (thus multiple 147 | // insertions to the same point will come out in the order they were added). 148 | // The double-@ is intended to make it unlikely that the generated code 149 | // could contain things that look like insertion points by accident. 150 | // 151 | // For example, the C++ code generator places the following line in the 152 | // .pb.h files that it generates: 153 | // // @@protoc_insertion_point(namespace_scope) 154 | // This line appears within the scope of the file's package namespace, but 155 | // outside of any particular class. Another plugin can then specify the 156 | // insertion_point "namespace_scope" to generate additional classes or 157 | // other declarations that should be placed in this scope. 158 | // 159 | // Note that if the line containing the insertion point begins with 160 | // whitespace, the same whitespace will be added to every line of the 161 | // inserted text. This is useful for languages like Python, where 162 | // indentation matters. In these languages, the insertion point comment 163 | // should be indented the same amount as any inserted code will need to be 164 | // in order to work correctly in that context. 165 | // 166 | // The code generator that generates the initial file and the one which 167 | // inserts into it must both run as part of a single invocation of protoc. 168 | // Code generators are executed in the order in which they appear on the 169 | // command line. 170 | // 171 | // If |insertion_point| is present, |name| must also be present. 172 | optional string insertion_point = 2; 173 | 174 | // The file contents. 175 | optional string content = 15; 176 | 177 | // Information describing the file content being inserted. If an insertion 178 | // point is used, this information will be appropriately offset and inserted 179 | // into the code generation metadata for the generated files. 180 | optional GeneratedCodeInfo generated_code_info = 16; 181 | } 182 | repeated File file = 15; 183 | } 184 | -------------------------------------------------------------------------------- /third_party/google/protobuf/duration.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "google.golang.org/protobuf/types/known/durationpb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "DurationProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // A Duration represents a signed, fixed-length span of time represented 44 | // as a count of seconds and fractions of seconds at nanosecond 45 | // resolution. It is independent of any calendar and concepts like "day" 46 | // or "month". It is related to Timestamp in that the difference between 47 | // two Timestamp values is a Duration and it can be added or subtracted 48 | // from a Timestamp. Range is approximately +-10,000 years. 49 | // 50 | // # Examples 51 | // 52 | // Example 1: Compute Duration from two Timestamps in pseudo code. 53 | // 54 | // Timestamp start = ...; 55 | // Timestamp end = ...; 56 | // Duration duration = ...; 57 | // 58 | // duration.seconds = end.seconds - start.seconds; 59 | // duration.nanos = end.nanos - start.nanos; 60 | // 61 | // if (duration.seconds < 0 && duration.nanos > 0) { 62 | // duration.seconds += 1; 63 | // duration.nanos -= 1000000000; 64 | // } else if (duration.seconds > 0 && duration.nanos < 0) { 65 | // duration.seconds -= 1; 66 | // duration.nanos += 1000000000; 67 | // } 68 | // 69 | // Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. 70 | // 71 | // Timestamp start = ...; 72 | // Duration duration = ...; 73 | // Timestamp end = ...; 74 | // 75 | // end.seconds = start.seconds + duration.seconds; 76 | // end.nanos = start.nanos + duration.nanos; 77 | // 78 | // if (end.nanos < 0) { 79 | // end.seconds -= 1; 80 | // end.nanos += 1000000000; 81 | // } else if (end.nanos >= 1000000000) { 82 | // end.seconds += 1; 83 | // end.nanos -= 1000000000; 84 | // } 85 | // 86 | // Example 3: Compute Duration from datetime.timedelta in Python. 87 | // 88 | // td = datetime.timedelta(days=3, minutes=10) 89 | // duration = Duration() 90 | // duration.FromTimedelta(td) 91 | // 92 | // # JSON Mapping 93 | // 94 | // In JSON format, the Duration type is encoded as a string rather than an 95 | // object, where the string ends in the suffix "s" (indicating seconds) and 96 | // is preceded by the number of seconds, with nanoseconds expressed as 97 | // fractional seconds. For example, 3 seconds with 0 nanoseconds should be 98 | // encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should 99 | // be expressed in JSON format as "3.000000001s", and 3 seconds and 1 100 | // microsecond should be expressed in JSON format as "3.000001s". 101 | // 102 | // 103 | message Duration { 104 | // Signed seconds of the span of time. Must be from -315,576,000,000 105 | // to +315,576,000,000 inclusive. Note: these bounds are computed from: 106 | // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years 107 | int64 seconds = 1; 108 | 109 | // Signed fractions of a second at nanosecond resolution of the span 110 | // of time. Durations less than one second are represented with a 0 111 | // `seconds` field and a positive or negative `nanos` field. For durations 112 | // of one second or more, a non-zero value for the `nanos` field must be 113 | // of the same sign as the `seconds` field. Must be from -999,999,999 114 | // to +999,999,999 inclusive. 115 | int32 nanos = 2; 116 | } 117 | -------------------------------------------------------------------------------- /third_party/google/protobuf/empty.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option go_package = "google.golang.org/protobuf/types/known/emptypb"; 37 | option java_package = "com.google.protobuf"; 38 | option java_outer_classname = "EmptyProto"; 39 | option java_multiple_files = true; 40 | option objc_class_prefix = "GPB"; 41 | option cc_enable_arenas = true; 42 | 43 | // A generic empty message that you can re-use to avoid defining duplicated 44 | // empty messages in your APIs. A typical example is to use it as the request 45 | // or the response type of an API method. For instance: 46 | // 47 | // service Foo { 48 | // rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); 49 | // } 50 | // 51 | // The JSON representation for `Empty` is empty JSON object `{}`. 52 | message Empty {} 53 | -------------------------------------------------------------------------------- /third_party/google/protobuf/field_mask.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option java_package = "com.google.protobuf"; 37 | option java_outer_classname = "FieldMaskProto"; 38 | option java_multiple_files = true; 39 | option objc_class_prefix = "GPB"; 40 | option go_package = "google.golang.org/protobuf/types/known/fieldmaskpb"; 41 | option cc_enable_arenas = true; 42 | 43 | // `FieldMask` represents a set of symbolic field paths, for example: 44 | // 45 | // paths: "f.a" 46 | // paths: "f.b.d" 47 | // 48 | // Here `f` represents a field in some root message, `a` and `b` 49 | // fields in the message found in `f`, and `d` a field found in the 50 | // message in `f.b`. 51 | // 52 | // Field masks are used to specify a subset of fields that should be 53 | // returned by a get operation or modified by an update operation. 54 | // Field masks also have a custom JSON encoding (see below). 55 | // 56 | // # Field Masks in Projections 57 | // 58 | // When used in the context of a projection, a response message or 59 | // sub-message is filtered by the API to only contain those fields as 60 | // specified in the mask. For example, if the mask in the previous 61 | // example is applied to a response message as follows: 62 | // 63 | // f { 64 | // a : 22 65 | // b { 66 | // d : 1 67 | // x : 2 68 | // } 69 | // y : 13 70 | // } 71 | // z: 8 72 | // 73 | // The result will not contain specific values for fields x,y and z 74 | // (their value will be set to the default, and omitted in proto text 75 | // output): 76 | // 77 | // 78 | // f { 79 | // a : 22 80 | // b { 81 | // d : 1 82 | // } 83 | // } 84 | // 85 | // A repeated field is not allowed except at the last position of a 86 | // paths string. 87 | // 88 | // If a FieldMask object is not present in a get operation, the 89 | // operation applies to all fields (as if a FieldMask of all fields 90 | // had been specified). 91 | // 92 | // Note that a field mask does not necessarily apply to the 93 | // top-level response message. In case of a REST get operation, the 94 | // field mask applies directly to the response, but in case of a REST 95 | // list operation, the mask instead applies to each individual message 96 | // in the returned resource list. In case of a REST custom method, 97 | // other definitions may be used. Where the mask applies will be 98 | // clearly documented together with its declaration in the API. In 99 | // any case, the effect on the returned resource/resources is required 100 | // behavior for APIs. 101 | // 102 | // # Field Masks in Update Operations 103 | // 104 | // A field mask in update operations specifies which fields of the 105 | // targeted resource are going to be updated. The API is required 106 | // to only change the values of the fields as specified in the mask 107 | // and leave the others untouched. If a resource is passed in to 108 | // describe the updated values, the API ignores the values of all 109 | // fields not covered by the mask. 110 | // 111 | // If a repeated field is specified for an update operation, new values will 112 | // be appended to the existing repeated field in the target resource. Note that 113 | // a repeated field is only allowed in the last position of a `paths` string. 114 | // 115 | // If a sub-message is specified in the last position of the field mask for an 116 | // update operation, then new value will be merged into the existing sub-message 117 | // in the target resource. 118 | // 119 | // For example, given the target message: 120 | // 121 | // f { 122 | // b { 123 | // d: 1 124 | // x: 2 125 | // } 126 | // c: [1] 127 | // } 128 | // 129 | // And an update message: 130 | // 131 | // f { 132 | // b { 133 | // d: 10 134 | // } 135 | // c: [2] 136 | // } 137 | // 138 | // then if the field mask is: 139 | // 140 | // paths: ["f.b", "f.c"] 141 | // 142 | // then the result will be: 143 | // 144 | // f { 145 | // b { 146 | // d: 10 147 | // x: 2 148 | // } 149 | // c: [1, 2] 150 | // } 151 | // 152 | // An implementation may provide options to override this default behavior for 153 | // repeated and message fields. 154 | // 155 | // In order to reset a field's value to the default, the field must 156 | // be in the mask and set to the default value in the provided resource. 157 | // Hence, in order to reset all fields of a resource, provide a default 158 | // instance of the resource and set all fields in the mask, or do 159 | // not provide a mask as described below. 160 | // 161 | // If a field mask is not present on update, the operation applies to 162 | // all fields (as if a field mask of all fields has been specified). 163 | // Note that in the presence of schema evolution, this may mean that 164 | // fields the client does not know and has therefore not filled into 165 | // the request will be reset to their default. If this is unwanted 166 | // behavior, a specific service may require a client to always specify 167 | // a field mask, producing an error if not. 168 | // 169 | // As with get operations, the location of the resource which 170 | // describes the updated values in the request message depends on the 171 | // operation kind. In any case, the effect of the field mask is 172 | // required to be honored by the API. 173 | // 174 | // ## Considerations for HTTP REST 175 | // 176 | // The HTTP kind of an update operation which uses a field mask must 177 | // be set to PATCH instead of PUT in order to satisfy HTTP semantics 178 | // (PUT must only be used for full updates). 179 | // 180 | // # JSON Encoding of Field Masks 181 | // 182 | // In JSON, a field mask is encoded as a single string where paths are 183 | // separated by a comma. Fields name in each path are converted 184 | // to/from lower-camel naming conventions. 185 | // 186 | // As an example, consider the following message declarations: 187 | // 188 | // message Profile { 189 | // User user = 1; 190 | // Photo photo = 2; 191 | // } 192 | // message User { 193 | // string display_name = 1; 194 | // string address = 2; 195 | // } 196 | // 197 | // In proto a field mask for `Profile` may look as such: 198 | // 199 | // mask { 200 | // paths: "user.display_name" 201 | // paths: "photo" 202 | // } 203 | // 204 | // In JSON, the same mask is represented as below: 205 | // 206 | // { 207 | // mask: "user.displayName,photo" 208 | // } 209 | // 210 | // # Field Masks and Oneof Fields 211 | // 212 | // Field masks treat fields in oneofs just as regular fields. Consider the 213 | // following message: 214 | // 215 | // message SampleMessage { 216 | // oneof test_oneof { 217 | // string name = 4; 218 | // SubMessage sub_message = 9; 219 | // } 220 | // } 221 | // 222 | // The field mask can be: 223 | // 224 | // mask { 225 | // paths: "name" 226 | // } 227 | // 228 | // Or: 229 | // 230 | // mask { 231 | // paths: "sub_message" 232 | // } 233 | // 234 | // Note that oneof type names ("test_oneof" in this case) cannot be used in 235 | // paths. 236 | // 237 | // ## Field Mask Verification 238 | // 239 | // The implementation of any API method which has a FieldMask type field in the 240 | // request should verify the included field paths, and return an 241 | // `INVALID_ARGUMENT` error if any path is unmappable. 242 | message FieldMask { 243 | // The set of field mask paths. 244 | repeated string paths = 1; 245 | } 246 | -------------------------------------------------------------------------------- /third_party/google/protobuf/source_context.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option java_package = "com.google.protobuf"; 37 | option java_outer_classname = "SourceContextProto"; 38 | option java_multiple_files = true; 39 | option objc_class_prefix = "GPB"; 40 | option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb"; 41 | 42 | // `SourceContext` represents information about the source of a 43 | // protobuf element, like the file in which it is defined. 44 | message SourceContext { 45 | // The path-qualified name of the .proto file that contained the associated 46 | // protobuf element. For example: `"google/protobuf/source_context.proto"`. 47 | string file_name = 1; 48 | } 49 | -------------------------------------------------------------------------------- /third_party/google/protobuf/struct.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "google.golang.org/protobuf/types/known/structpb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "StructProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // `Struct` represents a structured data value, consisting of fields 44 | // which map to dynamically typed values. In some languages, `Struct` 45 | // might be supported by a native representation. For example, in 46 | // scripting languages like JS a struct is represented as an 47 | // object. The details of that representation are described together 48 | // with the proto support for the language. 49 | // 50 | // The JSON representation for `Struct` is JSON object. 51 | message Struct { 52 | // Unordered map of dynamically typed values. 53 | map fields = 1; 54 | } 55 | 56 | // `Value` represents a dynamically typed value which can be either 57 | // null, a number, a string, a boolean, a recursive struct value, or a 58 | // list of values. A producer of value is expected to set one of that 59 | // variants, absence of any variant indicates an error. 60 | // 61 | // The JSON representation for `Value` is JSON value. 62 | message Value { 63 | // The kind of value. 64 | oneof kind { 65 | // Represents a null value. 66 | NullValue null_value = 1; 67 | // Represents a double value. 68 | double number_value = 2; 69 | // Represents a string value. 70 | string string_value = 3; 71 | // Represents a boolean value. 72 | bool bool_value = 4; 73 | // Represents a structured value. 74 | Struct struct_value = 5; 75 | // Represents a repeated `Value`. 76 | ListValue list_value = 6; 77 | } 78 | } 79 | 80 | // `NullValue` is a singleton enumeration to represent the null value for the 81 | // `Value` type union. 82 | // 83 | // The JSON representation for `NullValue` is JSON `null`. 84 | enum NullValue { 85 | // Null value. 86 | NULL_VALUE = 0; 87 | } 88 | 89 | // `ListValue` is a wrapper around a repeated field of values. 90 | // 91 | // The JSON representation for `ListValue` is JSON array. 92 | message ListValue { 93 | // Repeated field of dynamically typed values. 94 | repeated Value values = 1; 95 | } 96 | -------------------------------------------------------------------------------- /third_party/google/protobuf/timestamp.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "google.golang.org/protobuf/types/known/timestamppb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "TimestampProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // A Timestamp represents a point in time independent of any time zone or local 44 | // calendar, encoded as a count of seconds and fractions of seconds at 45 | // nanosecond resolution. The count is relative to an epoch at UTC midnight on 46 | // January 1, 1970, in the proleptic Gregorian calendar which extends the 47 | // Gregorian calendar backwards to year one. 48 | // 49 | // All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap 50 | // second table is needed for interpretation, using a [24-hour linear 51 | // smear](https://developers.google.com/time/smear). 52 | // 53 | // The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By 54 | // restricting to that range, we ensure that we can convert to and from [RFC 55 | // 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. 56 | // 57 | // # Examples 58 | // 59 | // Example 1: Compute Timestamp from POSIX `time()`. 60 | // 61 | // Timestamp timestamp; 62 | // timestamp.set_seconds(time(NULL)); 63 | // timestamp.set_nanos(0); 64 | // 65 | // Example 2: Compute Timestamp from POSIX `gettimeofday()`. 66 | // 67 | // struct timeval tv; 68 | // gettimeofday(&tv, NULL); 69 | // 70 | // Timestamp timestamp; 71 | // timestamp.set_seconds(tv.tv_sec); 72 | // timestamp.set_nanos(tv.tv_usec * 1000); 73 | // 74 | // Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. 75 | // 76 | // FILETIME ft; 77 | // GetSystemTimeAsFileTime(&ft); 78 | // UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; 79 | // 80 | // // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z 81 | // // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. 82 | // Timestamp timestamp; 83 | // timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); 84 | // timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); 85 | // 86 | // Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. 87 | // 88 | // long millis = System.currentTimeMillis(); 89 | // 90 | // Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) 91 | // .setNanos((int) ((millis % 1000) * 1000000)).build(); 92 | // 93 | // 94 | // Example 5: Compute Timestamp from Java `Instant.now()`. 95 | // 96 | // Instant now = Instant.now(); 97 | // 98 | // Timestamp timestamp = 99 | // Timestamp.newBuilder().setSeconds(now.getEpochSecond()) 100 | // .setNanos(now.getNano()).build(); 101 | // 102 | // 103 | // Example 6: Compute Timestamp from current time in Python. 104 | // 105 | // timestamp = Timestamp() 106 | // timestamp.GetCurrentTime() 107 | // 108 | // # JSON Mapping 109 | // 110 | // In JSON format, the Timestamp type is encoded as a string in the 111 | // [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the 112 | // format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" 113 | // where {year} is always expressed using four digits while {month}, {day}, 114 | // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional 115 | // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), 116 | // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone 117 | // is required. A proto3 JSON serializer should always use UTC (as indicated by 118 | // "Z") when printing the Timestamp type and a proto3 JSON parser should be 119 | // able to accept both UTC and other timezones (as indicated by an offset). 120 | // 121 | // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past 122 | // 01:30 UTC on January 15, 2017. 123 | // 124 | // In JavaScript, one can convert a Date object to this format using the 125 | // standard 126 | // [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) 127 | // method. In Python, a standard `datetime.datetime` object can be converted 128 | // to this format using 129 | // [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with 130 | // the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use 131 | // the Joda Time's [`ISODateTimeFormat.dateTime()`]( 132 | // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D 133 | // ) to obtain a formatter capable of generating timestamps in this format. 134 | // 135 | // 136 | message Timestamp { 137 | // Represents seconds of UTC time since Unix epoch 138 | // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 139 | // 9999-12-31T23:59:59Z inclusive. 140 | int64 seconds = 1; 141 | 142 | // Non-negative fractions of a second at nanosecond resolution. Negative 143 | // second values with fractions must still have non-negative nanos values 144 | // that count forward in time. Must be from 0 to 999,999,999 145 | // inclusive. 146 | int32 nanos = 2; 147 | } 148 | -------------------------------------------------------------------------------- /third_party/google/protobuf/type.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | import "google/protobuf/any.proto"; 36 | import "google/protobuf/source_context.proto"; 37 | 38 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 39 | option cc_enable_arenas = true; 40 | option java_package = "com.google.protobuf"; 41 | option java_outer_classname = "TypeProto"; 42 | option java_multiple_files = true; 43 | option objc_class_prefix = "GPB"; 44 | option go_package = "google.golang.org/protobuf/types/known/typepb"; 45 | 46 | // A protocol buffer message type. 47 | message Type { 48 | // The fully qualified message name. 49 | string name = 1; 50 | // The list of fields. 51 | repeated Field fields = 2; 52 | // The list of types appearing in `oneof` definitions in this type. 53 | repeated string oneofs = 3; 54 | // The protocol buffer options. 55 | repeated Option options = 4; 56 | // The source context. 57 | SourceContext source_context = 5; 58 | // The source syntax. 59 | Syntax syntax = 6; 60 | } 61 | 62 | // A single field of a message type. 63 | message Field { 64 | // Basic field types. 65 | enum Kind { 66 | // Field type unknown. 67 | TYPE_UNKNOWN = 0; 68 | // Field type double. 69 | TYPE_DOUBLE = 1; 70 | // Field type float. 71 | TYPE_FLOAT = 2; 72 | // Field type int64. 73 | TYPE_INT64 = 3; 74 | // Field type uint64. 75 | TYPE_UINT64 = 4; 76 | // Field type int32. 77 | TYPE_INT32 = 5; 78 | // Field type fixed64. 79 | TYPE_FIXED64 = 6; 80 | // Field type fixed32. 81 | TYPE_FIXED32 = 7; 82 | // Field type bool. 83 | TYPE_BOOL = 8; 84 | // Field type string. 85 | TYPE_STRING = 9; 86 | // Field type group. Proto2 syntax only, and deprecated. 87 | TYPE_GROUP = 10; 88 | // Field type message. 89 | TYPE_MESSAGE = 11; 90 | // Field type bytes. 91 | TYPE_BYTES = 12; 92 | // Field type uint32. 93 | TYPE_UINT32 = 13; 94 | // Field type enum. 95 | TYPE_ENUM = 14; 96 | // Field type sfixed32. 97 | TYPE_SFIXED32 = 15; 98 | // Field type sfixed64. 99 | TYPE_SFIXED64 = 16; 100 | // Field type sint32. 101 | TYPE_SINT32 = 17; 102 | // Field type sint64. 103 | TYPE_SINT64 = 18; 104 | } 105 | 106 | // Whether a field is optional, required, or repeated. 107 | enum Cardinality { 108 | // For fields with unknown cardinality. 109 | CARDINALITY_UNKNOWN = 0; 110 | // For optional fields. 111 | CARDINALITY_OPTIONAL = 1; 112 | // For required fields. Proto2 syntax only. 113 | CARDINALITY_REQUIRED = 2; 114 | // For repeated fields. 115 | CARDINALITY_REPEATED = 3; 116 | } 117 | 118 | // The field type. 119 | Kind kind = 1; 120 | // The field cardinality. 121 | Cardinality cardinality = 2; 122 | // The field number. 123 | int32 number = 3; 124 | // The field name. 125 | string name = 4; 126 | // The field type URL, without the scheme, for message or enumeration 127 | // types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. 128 | string type_url = 6; 129 | // The index of the field type in `Type.oneofs`, for message or enumeration 130 | // types. The first type has index 1; zero means the type is not in the list. 131 | int32 oneof_index = 7; 132 | // Whether to use alternative packed wire representation. 133 | bool packed = 8; 134 | // The protocol buffer options. 135 | repeated Option options = 9; 136 | // The field JSON name. 137 | string json_name = 10; 138 | // The string value of the default value of this field. Proto2 syntax only. 139 | string default_value = 11; 140 | } 141 | 142 | // Enum type definition. 143 | message Enum { 144 | // Enum type name. 145 | string name = 1; 146 | // Enum value definitions. 147 | repeated EnumValue enumvalue = 2; 148 | // Protocol buffer options. 149 | repeated Option options = 3; 150 | // The source context. 151 | SourceContext source_context = 4; 152 | // The source syntax. 153 | Syntax syntax = 5; 154 | } 155 | 156 | // Enum value definition. 157 | message EnumValue { 158 | // Enum value name. 159 | string name = 1; 160 | // Enum value number. 161 | int32 number = 2; 162 | // Protocol buffer options. 163 | repeated Option options = 3; 164 | } 165 | 166 | // A protocol buffer option, which can be attached to a message, field, 167 | // enumeration, etc. 168 | message Option { 169 | // The option's name. For protobuf built-in options (options defined in 170 | // descriptor.proto), this is the short name. For example, `"map_entry"`. 171 | // For custom options, it should be the fully-qualified name. For example, 172 | // `"google.api.http"`. 173 | string name = 1; 174 | // The option's value packed in an Any message. If the value is a primitive, 175 | // the corresponding wrapper type defined in google/protobuf/wrappers.proto 176 | // should be used. If the value is an enum, it should be stored as an int32 177 | // value using the google.protobuf.Int32Value type. 178 | Any value = 2; 179 | } 180 | 181 | // The syntax in which a protocol buffer element is defined. 182 | enum Syntax { 183 | // Syntax `proto2`. 184 | SYNTAX_PROTO2 = 0; 185 | // Syntax `proto3`. 186 | SYNTAX_PROTO3 = 1; 187 | } 188 | -------------------------------------------------------------------------------- /third_party/google/protobuf/wrappers.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Wrappers for primitive (non-message) types. These types are useful 32 | // for embedding primitives in the `google.protobuf.Any` type and for places 33 | // where we need to distinguish between the absence of a primitive 34 | // typed field and its default value. 35 | // 36 | // These wrappers have no meaningful use within repeated fields as they lack 37 | // the ability to detect presence on individual elements. 38 | // These wrappers have no meaningful use within a map or a oneof since 39 | // individual entries of a map or fields of a oneof can already detect presence. 40 | 41 | syntax = "proto3"; 42 | 43 | package google.protobuf; 44 | 45 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 46 | option cc_enable_arenas = true; 47 | option go_package = "google.golang.org/protobuf/types/known/wrapperspb"; 48 | option java_package = "com.google.protobuf"; 49 | option java_outer_classname = "WrappersProto"; 50 | option java_multiple_files = true; 51 | option objc_class_prefix = "GPB"; 52 | 53 | // Wrapper message for `double`. 54 | // 55 | // The JSON representation for `DoubleValue` is JSON number. 56 | message DoubleValue { 57 | // The double value. 58 | double value = 1; 59 | } 60 | 61 | // Wrapper message for `float`. 62 | // 63 | // The JSON representation for `FloatValue` is JSON number. 64 | message FloatValue { 65 | // The float value. 66 | float value = 1; 67 | } 68 | 69 | // Wrapper message for `int64`. 70 | // 71 | // The JSON representation for `Int64Value` is JSON string. 72 | message Int64Value { 73 | // The int64 value. 74 | int64 value = 1; 75 | } 76 | 77 | // Wrapper message for `uint64`. 78 | // 79 | // The JSON representation for `UInt64Value` is JSON string. 80 | message UInt64Value { 81 | // The uint64 value. 82 | uint64 value = 1; 83 | } 84 | 85 | // Wrapper message for `int32`. 86 | // 87 | // The JSON representation for `Int32Value` is JSON number. 88 | message Int32Value { 89 | // The int32 value. 90 | int32 value = 1; 91 | } 92 | 93 | // Wrapper message for `uint32`. 94 | // 95 | // The JSON representation for `UInt32Value` is JSON number. 96 | message UInt32Value { 97 | // The uint32 value. 98 | uint32 value = 1; 99 | } 100 | 101 | // Wrapper message for `bool`. 102 | // 103 | // The JSON representation for `BoolValue` is JSON `true` and `false`. 104 | message BoolValue { 105 | // The bool value. 106 | bool value = 1; 107 | } 108 | 109 | // Wrapper message for `string`. 110 | // 111 | // The JSON representation for `StringValue` is JSON string. 112 | message StringValue { 113 | // The string value. 114 | string value = 1; 115 | } 116 | 117 | // Wrapper message for `bytes`. 118 | // 119 | // The JSON representation for `BytesValue` is JSON string. 120 | message BytesValue { 121 | // The bytes value. 122 | bytes value = 1; 123 | } 124 | --------------------------------------------------------------------------------