feat(examples/i18n) add i18n example (#1157)
* i18n example * enable * regenerate * readme * update doc * go mod tidy * update readme * go mod tidypull/1185/head
parent
e19730e4b6
commit
a7b1af764f
@ -0,0 +1,36 @@ |
|||||||
|
# Reference https://github.com/github/gitignore/blob/master/Go.gitignore |
||||||
|
# Binaries for programs and plugins |
||||||
|
*.exe |
||||||
|
*.exe~ |
||||||
|
*.dll |
||||||
|
*.so |
||||||
|
*.dylib |
||||||
|
|
||||||
|
# Test binary, built with `go test -c` |
||||||
|
*.test |
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE |
||||||
|
*.out |
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it) |
||||||
|
vendor/ |
||||||
|
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects) |
||||||
|
*.o |
||||||
|
*.a |
||||||
|
*.so |
||||||
|
|
||||||
|
# OS General |
||||||
|
Thumbs.db |
||||||
|
.DS_Store |
||||||
|
|
||||||
|
# project |
||||||
|
*.cert |
||||||
|
*.key |
||||||
|
*.log |
||||||
|
bin/ |
||||||
|
|
||||||
|
# Develop tools |
||||||
|
.vscode/ |
||||||
|
.idea/ |
||||||
|
*.swp |
@ -0,0 +1,24 @@ |
|||||||
|
FROM golang:1.15 AS builder |
||||||
|
|
||||||
|
COPY . /src |
||||||
|
WORKDIR /src |
||||||
|
|
||||||
|
RUN GOPROXY=https://goproxy.cn make build |
||||||
|
|
||||||
|
FROM debian:stable-slim |
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \ |
||||||
|
ca-certificates \ |
||||||
|
netbase \ |
||||||
|
&& rm -rf /var/lib/apt/lists/ \ |
||||||
|
&& apt-get autoremove -y && apt-get autoclean -y |
||||||
|
|
||||||
|
COPY --from=builder /src/bin /app |
||||||
|
|
||||||
|
WORKDIR /app |
||||||
|
|
||||||
|
EXPOSE 8000 |
||||||
|
EXPOSE 9000 |
||||||
|
VOLUME /data/conf |
||||||
|
|
||||||
|
CMD ["./server", "-conf", "/data/conf"] |
@ -0,0 +1,21 @@ |
|||||||
|
MIT License |
||||||
|
|
||||||
|
Copyright (c) 2020 go-kratos |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
of this software and associated documentation files (the "Software"), to deal |
||||||
|
in the Software without restriction, including without limitation the rights |
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
copies of the Software, and to permit persons to whom the Software is |
||||||
|
furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all |
||||||
|
copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
SOFTWARE. |
@ -0,0 +1,70 @@ |
|||||||
|
GOPATH:=$(shell go env GOPATH)
|
||||||
|
VERSION=$(shell git describe --tags --always)
|
||||||
|
INTERNAL_PROTO_FILES=$(shell find internal -name *.proto)
|
||||||
|
API_PROTO_FILES=$(shell find api -name *.proto)
|
||||||
|
|
||||||
|
.PHONY: init |
||||||
|
# init env
|
||||||
|
init: |
||||||
|
go get -u github.com/go-kratos/kratos/cmd/kratos/v2
|
||||||
|
go get -u google.golang.org/protobuf/cmd/protoc-gen-go
|
||||||
|
go get -u google.golang.org/grpc/cmd/protoc-gen-go-grpc
|
||||||
|
go get -u github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2
|
||||||
|
go get -u github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2
|
||||||
|
go get -u github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
|
||||||
|
go get -u github.com/envoyproxy/protoc-gen-validate
|
||||||
|
|
||||||
|
.PHONY: errors |
||||||
|
# generate errors code
|
||||||
|
errors: |
||||||
|
protoc --proto_path=. \
|
||||||
|
--proto_path=./third_party \
|
||||||
|
--go_out=paths=source_relative:. \
|
||||||
|
--go-errors_out=paths=source_relative:. \
|
||||||
|
$(API_PROTO_FILES)
|
||||||
|
|
||||||
|
.PHONY: config |
||||||
|
# generate internal proto
|
||||||
|
config: |
||||||
|
protoc --proto_path=. \
|
||||||
|
--proto_path=./third_party \
|
||||||
|
--go_out=paths=source_relative:. \
|
||||||
|
$(INTERNAL_PROTO_FILES)
|
||||||
|
|
||||||
|
.PHONY: api |
||||||
|
# generate api proto
|
||||||
|
api: |
||||||
|
protoc --proto_path=. \
|
||||||
|
--proto_path=./third_party \
|
||||||
|
--go_out=paths=source_relative:. \
|
||||||
|
--go-http_out=paths=source_relative:. \
|
||||||
|
--go-grpc_out=paths=source_relative:. \
|
||||||
|
--validate_out=paths=source_relative,lang=go:. \
|
||||||
|
--openapiv2_out . \
|
||||||
|
$(API_PROTO_FILES)
|
||||||
|
|
||||||
|
.PHONY: all |
||||||
|
# generate all
|
||||||
|
all: |
||||||
|
make api;
|
||||||
|
make errors;
|
||||||
|
make config;
|
||||||
|
|
||||||
|
# show help
|
||||||
|
help: |
||||||
|
@echo ''
|
||||||
|
@echo 'Usage:'
|
||||||
|
@echo ' make [target]'
|
||||||
|
@echo ''
|
||||||
|
@echo 'Targets:'
|
||||||
|
@awk '/^[a-zA-Z\-\_0-9]+:/ { \
|
||||||
|
helpMessage = match(lastLine, /^# (.*)/); \
|
||||||
|
if (helpMessage) { \
|
||||||
|
helpCommand = substr($$1, 0, index($$1, ":")-1); \
|
||||||
|
helpMessage = substr(lastLine, RSTART + 2, RLENGTH); \
|
||||||
|
printf "\033[36m%-22s\033[0m %s\n", helpCommand,helpMessage; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
{ lastLine = $$0 }' $(MAKEFILE_LIST)
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := help
|
@ -0,0 +1,136 @@ |
|||||||
|
# i18n Example |
||||||
|
This project is an demo for i18n usage. |
||||||
|
We integrated [go-i18n](https://github.com/nicksnyder/go-i18n) into our project for localization. |
||||||
|
|
||||||
|
We start with the project generate with `kratos-layout`, you could use `kratos new` to generate it. |
||||||
|
|
||||||
|
The following steps are applied. |
||||||
|
## Step 1: install |
||||||
|
Install the cli tool `goi18n` and the package. |
||||||
|
|
||||||
|
```bash |
||||||
|
go get -u github.com/nicksnyder/go-i18n/v2/goi18n |
||||||
|
go get -u github.com/nicksnyder/go-i18n |
||||||
|
``` |
||||||
|
|
||||||
|
## Step 2: implement and register the middleware |
||||||
|
There's a middleware in `internal/pkg/middleware/localize`, |
||||||
|
we implement this middleware, and register it into our http server in `internal/server/http.go`. |
||||||
|
We init the bundle and load our translation file(we will generate it later). |
||||||
|
For convenience, we hard-coded the translation file path here, you should avoid it in your project :) |
||||||
|
|
||||||
|
Also the middleware will extract `accept-language` header |
||||||
|
from our request, then set the correct `localizer` to the context. |
||||||
|
In our service request handler, we can use the `FromContext` method to get this `localizer` for localization. |
||||||
|
|
||||||
|
This middleware is so simple that we can show it as following: |
||||||
|
```go |
||||||
|
package localize |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"github.com/BurntSushi/toml" |
||||||
|
"github.com/nicksnyder/go-i18n/v2/i18n" |
||||||
|
"golang.org/x/text/language" |
||||||
|
|
||||||
|
"github.com/go-kratos/kratos/v2/middleware" |
||||||
|
"github.com/go-kratos/kratos/v2/transport" |
||||||
|
) |
||||||
|
|
||||||
|
type localizerKey struct{} |
||||||
|
|
||||||
|
func I18N() middleware.Middleware { |
||||||
|
bundle := i18n.NewBundle(language.English) |
||||||
|
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) |
||||||
|
bundle.MustLoadMessageFile("../../active.zh.toml") |
||||||
|
|
||||||
|
return func(handler middleware.Handler) middleware.Handler { |
||||||
|
return func(ctx context.Context, req interface{}) (reply interface{}, err error) { |
||||||
|
if tr, ok := transport.FromServerContext(ctx); ok { |
||||||
|
accept := tr.Header().Get("accept-language") |
||||||
|
println(accept) |
||||||
|
localizer := i18n.NewLocalizer(bundle, accept) |
||||||
|
ctx = context.WithValue(ctx, localizerKey{}, localizer) |
||||||
|
} |
||||||
|
return handler(ctx, req) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func FromContext(ctx context.Context) *i18n.Localizer { |
||||||
|
return ctx.Value(localizerKey{}).(*i18n.Localizer) |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## Step 3: |
||||||
|
Write our request handler code. |
||||||
|
In `internal/service/greeter.go`, we use `localize.FromContext(ctx)` to get the localizer, and write the string for localizing. |
||||||
|
You should write your message with golang template syntax. |
||||||
|
Notice that both `One` and `Other` fields must be filled or you will get an panic on translation file generation with `goi18n` tool. |
||||||
|
|
||||||
|
```go |
||||||
|
func (s *GreeterService) SayHello(ctx context.Context, in *v1.HelloRequest) (*v1.HelloReply, error) { |
||||||
|
s.log.WithContext(ctx).Infof("SayHello Received: %v", in.GetName()) |
||||||
|
|
||||||
|
if in.GetName() == "error" { |
||||||
|
return nil, v1.ErrorUserNotFound("user not found: %s", in.GetName()) |
||||||
|
} |
||||||
|
localizer := localize.FromContext(ctx) |
||||||
|
helloMsg, err := localizer.Localize(&i18n.LocalizeConfig{ |
||||||
|
DefaultMessage: &i18n.Message{ |
||||||
|
Description: "sayhello", |
||||||
|
ID: "sayHello", |
||||||
|
One: "Hello {{.Name}}", |
||||||
|
Other: "Hello {{.Name}}", |
||||||
|
}, |
||||||
|
TemplateData: map[string]interface{}{ |
||||||
|
"Name": in.Name, |
||||||
|
}, |
||||||
|
}) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
return &v1.HelloReply{Message: helloMsg}, nil |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## Step 3: Generate and translate |
||||||
|
|
||||||
|
In the root of this project, generate `active.en.toml` with |
||||||
|
```bash |
||||||
|
goi18n extract |
||||||
|
``` |
||||||
|
The string which should be translated will be extracted from your code, and write into `active.en.toml` |
||||||
|
You should create the empty target language file: |
||||||
|
```bash |
||||||
|
touch tranlate.zh.toml |
||||||
|
``` |
||||||
|
|
||||||
|
Then fill the translate file: |
||||||
|
```bash |
||||||
|
goi18n merge active.en.toml translate.zh.toml |
||||||
|
``` |
||||||
|
|
||||||
|
You should edit the `translate.zh.toml` to finish the translation work. We translate `Hello` to `你好` in Chinese. |
||||||
|
After that, you should rename this file to `active.zh.toml` |
||||||
|
And this file is the translation file that we load in the Step 2. |
||||||
|
You could also embed these translation files into your binaries for easier deployment. |
||||||
|
|
||||||
|
## Step 4: Run |
||||||
|
Go to `cmd/i18n/`, and run `go run .` to start the service. |
||||||
|
|
||||||
|
You could try with curl with `Accept-Language` header |
||||||
|
```bash |
||||||
|
curl "http://localhost:8000/helloworld/eric" \ |
||||||
|
-H 'Accept-Language: zh-CN' |
||||||
|
``` |
||||||
|
Will get the Chinese result `{"message":"你好 eric"}` |
||||||
|
|
||||||
|
And if no header: |
||||||
|
``` |
||||||
|
curl "http://localhost:8000/helloworld/eric" |
||||||
|
``` |
||||||
|
Will get the default English result `{"message":"Hello eric"}` |
||||||
|
|
||||||
|
## Reference |
||||||
|
* [go-i18n](https://github.com/nicksnyder/go-i18n) You could refer to this repository for more detailed document. |
@ -0,0 +1,4 @@ |
|||||||
|
[sayHello] |
||||||
|
description = "sayhello" |
||||||
|
one = "Hello {{.Name}}" |
||||||
|
other = "Hello {{.Name}}" |
@ -0,0 +1,4 @@ |
|||||||
|
[sayHello] |
||||||
|
description = "sayhello" |
||||||
|
hash = "sha1-52d93a5edde18c01bc0ec531f302116b43cdd635" |
||||||
|
other = "你好 {{.Name}}" |
@ -0,0 +1,138 @@ |
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.27.1
|
||||||
|
// protoc v3.6.1
|
||||||
|
// source: api/helloworld/v1/error_reason.proto
|
||||||
|
|
||||||
|
package v1 |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "github.com/go-kratos/kratos/v2/errors" |
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect" |
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl" |
||||||
|
reflect "reflect" |
||||||
|
sync "sync" |
||||||
|
) |
||||||
|
|
||||||
|
const ( |
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) |
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) |
||||||
|
) |
||||||
|
|
||||||
|
type ErrorReason int32 |
||||||
|
|
||||||
|
const ( |
||||||
|
ErrorReason_USER_NOT_FOUND ErrorReason = 0 |
||||||
|
ErrorReason_CONTENT_MISSING ErrorReason = 1 |
||||||
|
) |
||||||
|
|
||||||
|
// Enum value maps for ErrorReason.
|
||||||
|
var ( |
||||||
|
ErrorReason_name = map[int32]string{ |
||||||
|
0: "USER_NOT_FOUND", |
||||||
|
1: "CONTENT_MISSING", |
||||||
|
} |
||||||
|
ErrorReason_value = map[string]int32{ |
||||||
|
"USER_NOT_FOUND": 0, |
||||||
|
"CONTENT_MISSING": 1, |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
func (x ErrorReason) Enum() *ErrorReason { |
||||||
|
p := new(ErrorReason) |
||||||
|
*p = x |
||||||
|
return p |
||||||
|
} |
||||||
|
|
||||||
|
func (x ErrorReason) String() string { |
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) |
||||||
|
} |
||||||
|
|
||||||
|
func (ErrorReason) Descriptor() protoreflect.EnumDescriptor { |
||||||
|
return file_api_helloworld_v1_error_reason_proto_enumTypes[0].Descriptor() |
||||||
|
} |
||||||
|
|
||||||
|
func (ErrorReason) Type() protoreflect.EnumType { |
||||||
|
return &file_api_helloworld_v1_error_reason_proto_enumTypes[0] |
||||||
|
} |
||||||
|
|
||||||
|
func (x ErrorReason) Number() protoreflect.EnumNumber { |
||||||
|
return protoreflect.EnumNumber(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use ErrorReason.Descriptor instead.
|
||||||
|
func (ErrorReason) EnumDescriptor() ([]byte, []int) { |
||||||
|
return file_api_helloworld_v1_error_reason_proto_rawDescGZIP(), []int{0} |
||||||
|
} |
||||||
|
|
||||||
|
var File_api_helloworld_v1_error_reason_proto protoreflect.FileDescriptor |
||||||
|
|
||||||
|
var file_api_helloworld_v1_error_reason_proto_rawDesc = []byte{ |
||||||
|
0x0a, 0x24, 0x61, 0x70, 0x69, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, |
||||||
|
0x2f, 0x76, 0x31, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, |
||||||
|
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x61, 0x70, 0x69, 0x2e, 0x62, 0x6c, 0x6f, 0x67, |
||||||
|
0x2e, 0x76, 0x31, 0x1a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2f, 0x65, 0x72, 0x72, 0x6f, |
||||||
|
0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0x48, 0x0a, 0x0b, 0x45, 0x72, 0x72, 0x6f, |
||||||
|
0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x0e, 0x55, 0x53, 0x45, 0x52, 0x5f, |
||||||
|
0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x00, 0x1a, 0x04, 0xa8, 0x45, 0x94, |
||||||
|
0x03, 0x12, 0x19, 0x0a, 0x0f, 0x43, 0x4f, 0x4e, 0x54, 0x45, 0x4e, 0x54, 0x5f, 0x4d, 0x49, 0x53, |
||||||
|
0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x90, 0x03, 0x1a, 0x04, 0xa0, 0x45, |
||||||
|
0xf4, 0x03, 0x42, 0x57, 0x0a, 0x0e, 0x62, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x65, 0x72, |
||||||
|
0x72, 0x6f, 0x72, 0x73, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, |
||||||
|
0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x6b, 0x72, 0x61, |
||||||
|
0x74, 0x6f, 0x73, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x62, 0x6c, 0x6f, |
||||||
|
0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0xa2, 0x02, 0x0d, 0x41, 0x50, |
||||||
|
0x49, 0x42, 0x6c, 0x6f, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, |
||||||
|
0x74, 0x6f, 0x33, |
||||||
|
} |
||||||
|
|
||||||
|
var ( |
||||||
|
file_api_helloworld_v1_error_reason_proto_rawDescOnce sync.Once |
||||||
|
file_api_helloworld_v1_error_reason_proto_rawDescData = file_api_helloworld_v1_error_reason_proto_rawDesc |
||||||
|
) |
||||||
|
|
||||||
|
func file_api_helloworld_v1_error_reason_proto_rawDescGZIP() []byte { |
||||||
|
file_api_helloworld_v1_error_reason_proto_rawDescOnce.Do(func() { |
||||||
|
file_api_helloworld_v1_error_reason_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_helloworld_v1_error_reason_proto_rawDescData) |
||||||
|
}) |
||||||
|
return file_api_helloworld_v1_error_reason_proto_rawDescData |
||||||
|
} |
||||||
|
|
||||||
|
var file_api_helloworld_v1_error_reason_proto_enumTypes = make([]protoimpl.EnumInfo, 1) |
||||||
|
var file_api_helloworld_v1_error_reason_proto_goTypes = []interface{}{ |
||||||
|
(ErrorReason)(0), // 0: api.blog.v1.ErrorReason
|
||||||
|
} |
||||||
|
var file_api_helloworld_v1_error_reason_proto_depIdxs = []int32{ |
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
} |
||||||
|
|
||||||
|
func init() { file_api_helloworld_v1_error_reason_proto_init() } |
||||||
|
func file_api_helloworld_v1_error_reason_proto_init() { |
||||||
|
if File_api_helloworld_v1_error_reason_proto != nil { |
||||||
|
return |
||||||
|
} |
||||||
|
type x struct{} |
||||||
|
out := protoimpl.TypeBuilder{ |
||||||
|
File: protoimpl.DescBuilder{ |
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), |
||||||
|
RawDescriptor: file_api_helloworld_v1_error_reason_proto_rawDesc, |
||||||
|
NumEnums: 1, |
||||||
|
NumMessages: 0, |
||||||
|
NumExtensions: 0, |
||||||
|
NumServices: 0, |
||||||
|
}, |
||||||
|
GoTypes: file_api_helloworld_v1_error_reason_proto_goTypes, |
||||||
|
DependencyIndexes: file_api_helloworld_v1_error_reason_proto_depIdxs, |
||||||
|
EnumInfos: file_api_helloworld_v1_error_reason_proto_enumTypes, |
||||||
|
}.Build() |
||||||
|
File_api_helloworld_v1_error_reason_proto = out.File |
||||||
|
file_api_helloworld_v1_error_reason_proto_rawDesc = nil |
||||||
|
file_api_helloworld_v1_error_reason_proto_goTypes = nil |
||||||
|
file_api_helloworld_v1_error_reason_proto_depIdxs = nil |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
// Code generated by protoc-gen-validate. DO NOT EDIT.
|
||||||
|
// source: api/helloworld/v1/error_reason.proto
|
||||||
|
|
||||||
|
package v1 |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"errors" |
||||||
|
"fmt" |
||||||
|
"net" |
||||||
|
"net/mail" |
||||||
|
"net/url" |
||||||
|
"regexp" |
||||||
|
"strings" |
||||||
|
"time" |
||||||
|
"unicode/utf8" |
||||||
|
|
||||||
|
"google.golang.org/protobuf/types/known/anypb" |
||||||
|
) |
||||||
|
|
||||||
|
// ensure the imports are used
|
||||||
|
var ( |
||||||
|
_ = bytes.MinRead |
||||||
|
_ = errors.New("") |
||||||
|
_ = fmt.Print |
||||||
|
_ = utf8.UTFMax |
||||||
|
_ = (*regexp.Regexp)(nil) |
||||||
|
_ = (*strings.Reader)(nil) |
||||||
|
_ = net.IPv4len |
||||||
|
_ = time.Duration(0) |
||||||
|
_ = (*url.URL)(nil) |
||||||
|
_ = (*mail.Address)(nil) |
||||||
|
_ = anypb.Any{} |
||||||
|
) |
@ -0,0 +1,17 @@ |
|||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package api.blog.v1; |
||||||
|
import "errors/errors.proto"; |
||||||
|
|
||||||
|
// 多语言特定包名,用于源代码引用 |
||||||
|
option go_package = "github.com/go-kratos/kratos/examples/blog/api/v1;v1"; |
||||||
|
option java_multiple_files = true; |
||||||
|
option java_package = "blog.v1.errors"; |
||||||
|
option objc_class_prefix = "APIBlogErrors"; |
||||||
|
|
||||||
|
enum ErrorReason { |
||||||
|
option (errors.default_code) = 500; |
||||||
|
|
||||||
|
USER_NOT_FOUND = 0 [(errors.code) = 404]; |
||||||
|
CONTENT_MISSING = 1 [(errors.code) = 400];; |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
{ |
||||||
|
"swagger": "2.0", |
||||||
|
"info": { |
||||||
|
"title": "api/helloworld/v1/error_reason.proto", |
||||||
|
"version": "version not set" |
||||||
|
}, |
||||||
|
"consumes": [ |
||||||
|
"application/json" |
||||||
|
], |
||||||
|
"produces": [ |
||||||
|
"application/json" |
||||||
|
], |
||||||
|
"paths": {}, |
||||||
|
"definitions": { |
||||||
|
"protobufAny": { |
||||||
|
"type": "object", |
||||||
|
"properties": { |
||||||
|
"typeUrl": { |
||||||
|
"type": "string" |
||||||
|
}, |
||||||
|
"value": { |
||||||
|
"type": "string", |
||||||
|
"format": "byte" |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"rpcStatus": { |
||||||
|
"type": "object", |
||||||
|
"properties": { |
||||||
|
"code": { |
||||||
|
"type": "integer", |
||||||
|
"format": "int32" |
||||||
|
}, |
||||||
|
"message": { |
||||||
|
"type": "string" |
||||||
|
}, |
||||||
|
"details": { |
||||||
|
"type": "array", |
||||||
|
"items": { |
||||||
|
"$ref": "#/definitions/protobufAny" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
// Code generated by protoc-gen-go-errors. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1 |
||||||
|
|
||||||
|
import ( |
||||||
|
fmt "fmt" |
||||||
|
errors "github.com/go-kratos/kratos/v2/errors" |
||||||
|
) |
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the kratos package it is being compiled against.
|
||||||
|
const _ = errors.SupportPackageIsVersion1 |
||||||
|
|
||||||
|
func IsUserNotFound(err error) bool { |
||||||
|
e := errors.FromError(err) |
||||||
|
return e.Reason == ErrorReason_USER_NOT_FOUND.String() && e.Code == 404 |
||||||
|
} |
||||||
|
|
||||||
|
func ErrorUserNotFound(format string, args ...interface{}) *errors.Error { |
||||||
|
return errors.New(404, ErrorReason_USER_NOT_FOUND.String(), fmt.Sprintf(format, args...)) |
||||||
|
} |
||||||
|
|
||||||
|
func IsContentMissing(err error) bool { |
||||||
|
e := errors.FromError(err) |
||||||
|
return e.Reason == ErrorReason_CONTENT_MISSING.String() && e.Code == 400 |
||||||
|
} |
||||||
|
|
||||||
|
func ErrorContentMissing(format string, args ...interface{}) *errors.Error { |
||||||
|
return errors.New(400, ErrorReason_CONTENT_MISSING.String(), fmt.Sprintf(format, args...)) |
||||||
|
} |
@ -0,0 +1,226 @@ |
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.27.1
|
||||||
|
// protoc v3.6.1
|
||||||
|
// source: api/helloworld/v1/greeter.proto
|
||||||
|
|
||||||
|
package v1 |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "google.golang.org/genproto/googleapis/api/annotations" |
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect" |
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl" |
||||||
|
reflect "reflect" |
||||||
|
sync "sync" |
||||||
|
) |
||||||
|
|
||||||
|
const ( |
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) |
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) |
||||||
|
) |
||||||
|
|
||||||
|
// The request message containing the user's name.
|
||||||
|
type HelloRequest struct { |
||||||
|
state protoimpl.MessageState |
||||||
|
sizeCache protoimpl.SizeCache |
||||||
|
unknownFields protoimpl.UnknownFields |
||||||
|
|
||||||
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
func (x *HelloRequest) Reset() { |
||||||
|
*x = HelloRequest{} |
||||||
|
if protoimpl.UnsafeEnabled { |
||||||
|
mi := &file_api_helloworld_v1_greeter_proto_msgTypes[0] |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *HelloRequest) String() string { |
||||||
|
return protoimpl.X.MessageStringOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
func (*HelloRequest) ProtoMessage() {} |
||||||
|
|
||||||
|
func (x *HelloRequest) ProtoReflect() protoreflect.Message { |
||||||
|
mi := &file_api_helloworld_v1_greeter_proto_msgTypes[0] |
||||||
|
if protoimpl.UnsafeEnabled && x != nil { |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
if ms.LoadMessageInfo() == nil { |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
return ms |
||||||
|
} |
||||||
|
return mi.MessageOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*HelloRequest) Descriptor() ([]byte, []int) { |
||||||
|
return file_api_helloworld_v1_greeter_proto_rawDescGZIP(), []int{0} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *HelloRequest) GetName() string { |
||||||
|
if x != nil { |
||||||
|
return x.Name |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
// The response message containing the greetings
|
||||||
|
type HelloReply struct { |
||||||
|
state protoimpl.MessageState |
||||||
|
sizeCache protoimpl.SizeCache |
||||||
|
unknownFields protoimpl.UnknownFields |
||||||
|
|
||||||
|
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
func (x *HelloReply) Reset() { |
||||||
|
*x = HelloReply{} |
||||||
|
if protoimpl.UnsafeEnabled { |
||||||
|
mi := &file_api_helloworld_v1_greeter_proto_msgTypes[1] |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *HelloReply) String() string { |
||||||
|
return protoimpl.X.MessageStringOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
func (*HelloReply) ProtoMessage() {} |
||||||
|
|
||||||
|
func (x *HelloReply) ProtoReflect() protoreflect.Message { |
||||||
|
mi := &file_api_helloworld_v1_greeter_proto_msgTypes[1] |
||||||
|
if protoimpl.UnsafeEnabled && x != nil { |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
if ms.LoadMessageInfo() == nil { |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
return ms |
||||||
|
} |
||||||
|
return mi.MessageOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use HelloReply.ProtoReflect.Descriptor instead.
|
||||||
|
func (*HelloReply) Descriptor() ([]byte, []int) { |
||||||
|
return file_api_helloworld_v1_greeter_proto_rawDescGZIP(), []int{1} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *HelloReply) GetMessage() string { |
||||||
|
if x != nil { |
||||||
|
return x.Message |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
var File_api_helloworld_v1_greeter_proto protoreflect.FileDescriptor |
||||||
|
|
||||||
|
var file_api_helloworld_v1_greeter_proto_rawDesc = []byte{ |
||||||
|
0x0a, 0x1f, 0x61, 0x70, 0x69, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, |
||||||
|
0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, |
||||||
|
0x6f, 0x12, 0x0d, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x76, 0x31, |
||||||
|
0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, |
||||||
|
0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x22, |
||||||
|
0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, |
||||||
|
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, |
||||||
|
0x6d, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, |
||||||
|
0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, |
||||||
|
0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x69, 0x0a, 0x07, 0x47, 0x72, |
||||||
|
0x65, 0x65, 0x74, 0x65, 0x72, 0x12, 0x5e, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, |
||||||
|
0x6f, 0x12, 0x1b, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x76, |
||||||
|
0x31, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, |
||||||
|
0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x48, |
||||||
|
0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, |
||||||
|
0x14, 0x12, 0x12, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2f, 0x7b, |
||||||
|
0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x42, 0x73, 0x0a, 0x1c, 0x64, 0x65, 0x76, 0x2e, 0x6b, 0x72, 0x61, |
||||||
|
0x74, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, |
||||||
|
0x6c, 0x64, 0x2e, 0x76, 0x31, 0x42, 0x11, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x6f, 0x72, 0x6c, |
||||||
|
0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x56, 0x31, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, |
||||||
|
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, |
||||||
|
0x2f, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, |
||||||
|
0x2f, 0x69, 0x31, 0x38, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, |
||||||
|
0x6f, 0x72, 0x6c, 0x64, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, |
||||||
|
0x6f, 0x33, |
||||||
|
} |
||||||
|
|
||||||
|
var ( |
||||||
|
file_api_helloworld_v1_greeter_proto_rawDescOnce sync.Once |
||||||
|
file_api_helloworld_v1_greeter_proto_rawDescData = file_api_helloworld_v1_greeter_proto_rawDesc |
||||||
|
) |
||||||
|
|
||||||
|
func file_api_helloworld_v1_greeter_proto_rawDescGZIP() []byte { |
||||||
|
file_api_helloworld_v1_greeter_proto_rawDescOnce.Do(func() { |
||||||
|
file_api_helloworld_v1_greeter_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_helloworld_v1_greeter_proto_rawDescData) |
||||||
|
}) |
||||||
|
return file_api_helloworld_v1_greeter_proto_rawDescData |
||||||
|
} |
||||||
|
|
||||||
|
var file_api_helloworld_v1_greeter_proto_msgTypes = make([]protoimpl.MessageInfo, 2) |
||||||
|
var file_api_helloworld_v1_greeter_proto_goTypes = []interface{}{ |
||||||
|
(*HelloRequest)(nil), // 0: helloworld.v1.HelloRequest
|
||||||
|
(*HelloReply)(nil), // 1: helloworld.v1.HelloReply
|
||||||
|
} |
||||||
|
var file_api_helloworld_v1_greeter_proto_depIdxs = []int32{ |
||||||
|
0, // 0: helloworld.v1.Greeter.SayHello:input_type -> helloworld.v1.HelloRequest
|
||||||
|
1, // 1: helloworld.v1.Greeter.SayHello:output_type -> helloworld.v1.HelloReply
|
||||||
|
1, // [1:2] is the sub-list for method output_type
|
||||||
|
0, // [0:1] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
} |
||||||
|
|
||||||
|
func init() { file_api_helloworld_v1_greeter_proto_init() } |
||||||
|
func file_api_helloworld_v1_greeter_proto_init() { |
||||||
|
if File_api_helloworld_v1_greeter_proto != nil { |
||||||
|
return |
||||||
|
} |
||||||
|
if !protoimpl.UnsafeEnabled { |
||||||
|
file_api_helloworld_v1_greeter_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { |
||||||
|
switch v := v.(*HelloRequest); i { |
||||||
|
case 0: |
||||||
|
return &v.state |
||||||
|
case 1: |
||||||
|
return &v.sizeCache |
||||||
|
case 2: |
||||||
|
return &v.unknownFields |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
file_api_helloworld_v1_greeter_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { |
||||||
|
switch v := v.(*HelloReply); i { |
||||||
|
case 0: |
||||||
|
return &v.state |
||||||
|
case 1: |
||||||
|
return &v.sizeCache |
||||||
|
case 2: |
||||||
|
return &v.unknownFields |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
type x struct{} |
||||||
|
out := protoimpl.TypeBuilder{ |
||||||
|
File: protoimpl.DescBuilder{ |
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), |
||||||
|
RawDescriptor: file_api_helloworld_v1_greeter_proto_rawDesc, |
||||||
|
NumEnums: 0, |
||||||
|
NumMessages: 2, |
||||||
|
NumExtensions: 0, |
||||||
|
NumServices: 1, |
||||||
|
}, |
||||||
|
GoTypes: file_api_helloworld_v1_greeter_proto_goTypes, |
||||||
|
DependencyIndexes: file_api_helloworld_v1_greeter_proto_depIdxs, |
||||||
|
MessageInfos: file_api_helloworld_v1_greeter_proto_msgTypes, |
||||||
|
}.Build() |
||||||
|
File_api_helloworld_v1_greeter_proto = out.File |
||||||
|
file_api_helloworld_v1_greeter_proto_rawDesc = nil |
||||||
|
file_api_helloworld_v1_greeter_proto_goTypes = nil |
||||||
|
file_api_helloworld_v1_greeter_proto_depIdxs = nil |
||||||
|
} |
@ -0,0 +1,167 @@ |
|||||||
|
// Code generated by protoc-gen-validate. DO NOT EDIT.
|
||||||
|
// source: api/helloworld/v1/greeter.proto
|
||||||
|
|
||||||
|
package v1 |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"errors" |
||||||
|
"fmt" |
||||||
|
"net" |
||||||
|
"net/mail" |
||||||
|
"net/url" |
||||||
|
"regexp" |
||||||
|
"strings" |
||||||
|
"time" |
||||||
|
"unicode/utf8" |
||||||
|
|
||||||
|
"google.golang.org/protobuf/types/known/anypb" |
||||||
|
) |
||||||
|
|
||||||
|
// ensure the imports are used
|
||||||
|
var ( |
||||||
|
_ = bytes.MinRead |
||||||
|
_ = errors.New("") |
||||||
|
_ = fmt.Print |
||||||
|
_ = utf8.UTFMax |
||||||
|
_ = (*regexp.Regexp)(nil) |
||||||
|
_ = (*strings.Reader)(nil) |
||||||
|
_ = net.IPv4len |
||||||
|
_ = time.Duration(0) |
||||||
|
_ = (*url.URL)(nil) |
||||||
|
_ = (*mail.Address)(nil) |
||||||
|
_ = anypb.Any{} |
||||||
|
) |
||||||
|
|
||||||
|
// Validate checks the field values on HelloRequest with the rules defined in
|
||||||
|
// the proto definition for this message. If any rules are violated, an error
|
||||||
|
// is returned.
|
||||||
|
func (m *HelloRequest) Validate() error { |
||||||
|
if m == nil { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
// no validation rules for Name
|
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
// HelloRequestValidationError is the validation error returned by
|
||||||
|
// HelloRequest.Validate if the designated constraints aren't met.
|
||||||
|
type HelloRequestValidationError struct { |
||||||
|
field string |
||||||
|
reason string |
||||||
|
cause error |
||||||
|
key bool |
||||||
|
} |
||||||
|
|
||||||
|
// Field function returns field value.
|
||||||
|
func (e HelloRequestValidationError) Field() string { return e.field } |
||||||
|
|
||||||
|
// Reason function returns reason value.
|
||||||
|
func (e HelloRequestValidationError) Reason() string { return e.reason } |
||||||
|
|
||||||
|
// Cause function returns cause value.
|
||||||
|
func (e HelloRequestValidationError) Cause() error { return e.cause } |
||||||
|
|
||||||
|
// Key function returns key value.
|
||||||
|
func (e HelloRequestValidationError) Key() bool { return e.key } |
||||||
|
|
||||||
|
// ErrorName returns error name.
|
||||||
|
func (e HelloRequestValidationError) ErrorName() string { return "HelloRequestValidationError" } |
||||||
|
|
||||||
|
// Error satisfies the builtin error interface
|
||||||
|
func (e HelloRequestValidationError) Error() string { |
||||||
|
cause := "" |
||||||
|
if e.cause != nil { |
||||||
|
cause = fmt.Sprintf(" | caused by: %v", e.cause) |
||||||
|
} |
||||||
|
|
||||||
|
key := "" |
||||||
|
if e.key { |
||||||
|
key = "key for " |
||||||
|
} |
||||||
|
|
||||||
|
return fmt.Sprintf( |
||||||
|
"invalid %sHelloRequest.%s: %s%s", |
||||||
|
key, |
||||||
|
e.field, |
||||||
|
e.reason, |
||||||
|
cause) |
||||||
|
} |
||||||
|
|
||||||
|
var _ error = HelloRequestValidationError{} |
||||||
|
|
||||||
|
var _ interface { |
||||||
|
Field() string |
||||||
|
Reason() string |
||||||
|
Key() bool |
||||||
|
Cause() error |
||||||
|
ErrorName() string |
||||||
|
} = HelloRequestValidationError{} |
||||||
|
|
||||||
|
// Validate checks the field values on HelloReply with the rules defined in the
|
||||||
|
// proto definition for this message. If any rules are violated, an error is returned.
|
||||||
|
func (m *HelloReply) Validate() error { |
||||||
|
if m == nil { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
// no validation rules for Message
|
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
// HelloReplyValidationError is the validation error returned by
|
||||||
|
// HelloReply.Validate if the designated constraints aren't met.
|
||||||
|
type HelloReplyValidationError struct { |
||||||
|
field string |
||||||
|
reason string |
||||||
|
cause error |
||||||
|
key bool |
||||||
|
} |
||||||
|
|
||||||
|
// Field function returns field value.
|
||||||
|
func (e HelloReplyValidationError) Field() string { return e.field } |
||||||
|
|
||||||
|
// Reason function returns reason value.
|
||||||
|
func (e HelloReplyValidationError) Reason() string { return e.reason } |
||||||
|
|
||||||
|
// Cause function returns cause value.
|
||||||
|
func (e HelloReplyValidationError) Cause() error { return e.cause } |
||||||
|
|
||||||
|
// Key function returns key value.
|
||||||
|
func (e HelloReplyValidationError) Key() bool { return e.key } |
||||||
|
|
||||||
|
// ErrorName returns error name.
|
||||||
|
func (e HelloReplyValidationError) ErrorName() string { return "HelloReplyValidationError" } |
||||||
|
|
||||||
|
// Error satisfies the builtin error interface
|
||||||
|
func (e HelloReplyValidationError) Error() string { |
||||||
|
cause := "" |
||||||
|
if e.cause != nil { |
||||||
|
cause = fmt.Sprintf(" | caused by: %v", e.cause) |
||||||
|
} |
||||||
|
|
||||||
|
key := "" |
||||||
|
if e.key { |
||||||
|
key = "key for " |
||||||
|
} |
||||||
|
|
||||||
|
return fmt.Sprintf( |
||||||
|
"invalid %sHelloReply.%s: %s%s", |
||||||
|
key, |
||||||
|
e.field, |
||||||
|
e.reason, |
||||||
|
cause) |
||||||
|
} |
||||||
|
|
||||||
|
var _ error = HelloReplyValidationError{} |
||||||
|
|
||||||
|
var _ interface { |
||||||
|
Field() string |
||||||
|
Reason() string |
||||||
|
Key() bool |
||||||
|
Cause() error |
||||||
|
ErrorName() string |
||||||
|
} = HelloReplyValidationError{} |
@ -0,0 +1,30 @@ |
|||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package helloworld.v1; |
||||||
|
|
||||||
|
import "google/api/annotations.proto"; |
||||||
|
|
||||||
|
option go_package = "github.com/go-kratos/kratos/examples/i18n/api/helloworld/v1;v1"; |
||||||
|
option java_multiple_files = true; |
||||||
|
option java_package = "dev.kratos.api.helloworld.v1"; |
||||||
|
option java_outer_classname = "HelloWorldProtoV1"; |
||||||
|
|
||||||
|
// The greeting service definition. |
||||||
|
service Greeter { |
||||||
|
// Sends a greeting |
||||||
|
rpc SayHello (HelloRequest) returns (HelloReply) { |
||||||
|
option (google.api.http) = { |
||||||
|
get: "/helloworld/{name}" |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// The request message containing the user's name. |
||||||
|
message HelloRequest { |
||||||
|
string name = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// The response message containing the greetings |
||||||
|
message HelloReply { |
||||||
|
string message = 1; |
||||||
|
} |
@ -0,0 +1,92 @@ |
|||||||
|
{ |
||||||
|
"swagger": "2.0", |
||||||
|
"info": { |
||||||
|
"title": "api/helloworld/v1/greeter.proto", |
||||||
|
"version": "version not set" |
||||||
|
}, |
||||||
|
"tags": [ |
||||||
|
{ |
||||||
|
"name": "Greeter" |
||||||
|
} |
||||||
|
], |
||||||
|
"consumes": [ |
||||||
|
"application/json" |
||||||
|
], |
||||||
|
"produces": [ |
||||||
|
"application/json" |
||||||
|
], |
||||||
|
"paths": { |
||||||
|
"/helloworld/{name}": { |
||||||
|
"get": { |
||||||
|
"summary": "Sends a greeting", |
||||||
|
"operationId": "Greeter_SayHello", |
||||||
|
"responses": { |
||||||
|
"200": { |
||||||
|
"description": "A successful response.", |
||||||
|
"schema": { |
||||||
|
"$ref": "#/definitions/v1HelloReply" |
||||||
|
} |
||||||
|
}, |
||||||
|
"default": { |
||||||
|
"description": "An unexpected error response.", |
||||||
|
"schema": { |
||||||
|
"$ref": "#/definitions/rpcStatus" |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"parameters": [ |
||||||
|
{ |
||||||
|
"name": "name", |
||||||
|
"in": "path", |
||||||
|
"required": true, |
||||||
|
"type": "string" |
||||||
|
} |
||||||
|
], |
||||||
|
"tags": [ |
||||||
|
"Greeter" |
||||||
|
] |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"definitions": { |
||||||
|
"protobufAny": { |
||||||
|
"type": "object", |
||||||
|
"properties": { |
||||||
|
"typeUrl": { |
||||||
|
"type": "string" |
||||||
|
}, |
||||||
|
"value": { |
||||||
|
"type": "string", |
||||||
|
"format": "byte" |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"rpcStatus": { |
||||||
|
"type": "object", |
||||||
|
"properties": { |
||||||
|
"code": { |
||||||
|
"type": "integer", |
||||||
|
"format": "int32" |
||||||
|
}, |
||||||
|
"message": { |
||||||
|
"type": "string" |
||||||
|
}, |
||||||
|
"details": { |
||||||
|
"type": "array", |
||||||
|
"items": { |
||||||
|
"$ref": "#/definitions/protobufAny" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"v1HelloReply": { |
||||||
|
"type": "object", |
||||||
|
"properties": { |
||||||
|
"message": { |
||||||
|
"type": "string" |
||||||
|
} |
||||||
|
}, |
||||||
|
"title": "The response message containing the greetings" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1 |
||||||
|
|
||||||
|
import ( |
||||||
|
context "context" |
||||||
|
grpc "google.golang.org/grpc" |
||||||
|
codes "google.golang.org/grpc/codes" |
||||||
|
status "google.golang.org/grpc/status" |
||||||
|
) |
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
|
const _ = grpc.SupportPackageIsVersion7 |
||||||
|
|
||||||
|
// GreeterClient is the client API for Greeter service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
|
type GreeterClient interface { |
||||||
|
// Sends a greeting
|
||||||
|
SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) |
||||||
|
} |
||||||
|
|
||||||
|
type greeterClient struct { |
||||||
|
cc grpc.ClientConnInterface |
||||||
|
} |
||||||
|
|
||||||
|
func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { |
||||||
|
return &greeterClient{cc} |
||||||
|
} |
||||||
|
|
||||||
|
func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { |
||||||
|
out := new(HelloReply) |
||||||
|
err := c.cc.Invoke(ctx, "/helloworld.v1.Greeter/SayHello", in, out, opts...) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
return out, nil |
||||||
|
} |
||||||
|
|
||||||
|
// GreeterServer is the server API for Greeter service.
|
||||||
|
// All implementations must embed UnimplementedGreeterServer
|
||||||
|
// for forward compatibility
|
||||||
|
type GreeterServer interface { |
||||||
|
// Sends a greeting
|
||||||
|
SayHello(context.Context, *HelloRequest) (*HelloReply, error) |
||||||
|
mustEmbedUnimplementedGreeterServer() |
||||||
|
} |
||||||
|
|
||||||
|
// UnimplementedGreeterServer must be embedded to have forward compatible implementations.
|
||||||
|
type UnimplementedGreeterServer struct { |
||||||
|
} |
||||||
|
|
||||||
|
func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { |
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") |
||||||
|
} |
||||||
|
func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} |
||||||
|
|
||||||
|
// UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
// Use of this interface is not recommended, as added methods to GreeterServer will
|
||||||
|
// result in compilation errors.
|
||||||
|
type UnsafeGreeterServer interface { |
||||||
|
mustEmbedUnimplementedGreeterServer() |
||||||
|
} |
||||||
|
|
||||||
|
func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { |
||||||
|
s.RegisterService(&Greeter_ServiceDesc, srv) |
||||||
|
} |
||||||
|
|
||||||
|
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { |
||||||
|
in := new(HelloRequest) |
||||||
|
if err := dec(in); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
if interceptor == nil { |
||||||
|
return srv.(GreeterServer).SayHello(ctx, in) |
||||||
|
} |
||||||
|
info := &grpc.UnaryServerInfo{ |
||||||
|
Server: srv, |
||||||
|
FullMethod: "/helloworld.v1.Greeter/SayHello", |
||||||
|
} |
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) { |
||||||
|
return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) |
||||||
|
} |
||||||
|
return interceptor(ctx, in, info, handler) |
||||||
|
} |
||||||
|
|
||||||
|
// Greeter_ServiceDesc is the grpc.ServiceDesc for Greeter service.
|
||||||
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
var Greeter_ServiceDesc = grpc.ServiceDesc{ |
||||||
|
ServiceName: "helloworld.v1.Greeter", |
||||||
|
HandlerType: (*GreeterServer)(nil), |
||||||
|
Methods: []grpc.MethodDesc{ |
||||||
|
{ |
||||||
|
MethodName: "SayHello", |
||||||
|
Handler: _Greeter_SayHello_Handler, |
||||||
|
}, |
||||||
|
}, |
||||||
|
Streams: []grpc.StreamDesc{}, |
||||||
|
Metadata: "api/helloworld/v1/greeter.proto", |
||||||
|
} |
@ -0,0 +1,74 @@ |
|||||||
|
// Code generated by protoc-gen-go-http. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go-http v2.0.0-rc7
|
||||||
|
|
||||||
|
package v1 |
||||||
|
|
||||||
|
import ( |
||||||
|
context "context" |
||||||
|
http "github.com/go-kratos/kratos/v2/transport/http" |
||||||
|
binding "github.com/go-kratos/kratos/v2/transport/http/binding" |
||||||
|
) |
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the kratos package it is being compiled against.
|
||||||
|
var _ = new(context.Context) |
||||||
|
var _ = binding.EncodeURL |
||||||
|
|
||||||
|
const _ = http.SupportPackageIsVersion1 |
||||||
|
|
||||||
|
type GreeterHTTPServer interface { |
||||||
|
SayHello(context.Context, *HelloRequest) (*HelloReply, error) |
||||||
|
} |
||||||
|
|
||||||
|
func RegisterGreeterHTTPServer(s *http.Server, srv GreeterHTTPServer) { |
||||||
|
r := s.Route("/") |
||||||
|
r.GET("/helloworld/{name}", _Greeter_SayHello0_HTTP_Handler(srv)) |
||||||
|
} |
||||||
|
|
||||||
|
func _Greeter_SayHello0_HTTP_Handler(srv GreeterHTTPServer) func(ctx http.Context) error { |
||||||
|
return func(ctx http.Context) error { |
||||||
|
var in HelloRequest |
||||||
|
if err := ctx.BindQuery(&in); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
if err := ctx.BindVars(&in); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
http.SetOperation(ctx, "/helloworld.v1.Greeter/SayHello") |
||||||
|
h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { |
||||||
|
return srv.SayHello(ctx, req.(*HelloRequest)) |
||||||
|
}) |
||||||
|
out, err := h(ctx, &in) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
reply := out.(*HelloReply) |
||||||
|
return ctx.Result(200, reply) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
type GreeterHTTPClient interface { |
||||||
|
SayHello(ctx context.Context, req *HelloRequest, opts ...http.CallOption) (rsp *HelloReply, err error) |
||||||
|
} |
||||||
|
|
||||||
|
type GreeterHTTPClientImpl struct { |
||||||
|
cc *http.Client |
||||||
|
} |
||||||
|
|
||||||
|
func NewGreeterHTTPClient(client *http.Client) GreeterHTTPClient { |
||||||
|
return &GreeterHTTPClientImpl{client} |
||||||
|
} |
||||||
|
|
||||||
|
func (c *GreeterHTTPClientImpl) SayHello(ctx context.Context, in *HelloRequest, opts ...http.CallOption) (*HelloReply, error) { |
||||||
|
var out HelloReply |
||||||
|
pattern := "/helloworld/{name}" |
||||||
|
path := binding.EncodeURL(pattern, in, true) |
||||||
|
opts = append(opts, http.Operation("/helloworld.v1.Greeter/SayHello")) |
||||||
|
opts = append(opts, http.PathTemplate(pattern)) |
||||||
|
err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
return &out, err |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"flag" |
||||||
|
"os" |
||||||
|
|
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/conf" |
||||||
|
"github.com/go-kratos/kratos/v2" |
||||||
|
"github.com/go-kratos/kratos/v2/config" |
||||||
|
"github.com/go-kratos/kratos/v2/config/file" |
||||||
|
"github.com/go-kratos/kratos/v2/log" |
||||||
|
"github.com/go-kratos/kratos/v2/transport/grpc" |
||||||
|
"github.com/go-kratos/kratos/v2/transport/http" |
||||||
|
) |
||||||
|
|
||||||
|
// go build -ldflags "-X main.Version=x.y.z"
|
||||||
|
var ( |
||||||
|
// Name is the name of the compiled software.
|
||||||
|
Name string |
||||||
|
// Version is the version of the compiled software.
|
||||||
|
Version string |
||||||
|
// flagconf is the config flag.
|
||||||
|
flagconf string |
||||||
|
|
||||||
|
id, _ = os.Hostname() |
||||||
|
) |
||||||
|
|
||||||
|
func init() { |
||||||
|
flag.StringVar(&flagconf, "conf", "../../configs", "config path, eg: -conf config.yaml") |
||||||
|
} |
||||||
|
|
||||||
|
func newApp(logger log.Logger, hs *http.Server, gs *grpc.Server) *kratos.App { |
||||||
|
return kratos.New( |
||||||
|
kratos.ID(id), |
||||||
|
kratos.Name(Name), |
||||||
|
kratos.Version(Version), |
||||||
|
kratos.Metadata(map[string]string{}), |
||||||
|
kratos.Logger(logger), |
||||||
|
kratos.Server( |
||||||
|
hs, |
||||||
|
gs, |
||||||
|
), |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
func main() { |
||||||
|
flag.Parse() |
||||||
|
logger := log.With(log.NewStdLogger(os.Stdout), |
||||||
|
"ts", log.DefaultTimestamp, |
||||||
|
"caller", log.DefaultCaller, |
||||||
|
"service.id", id, |
||||||
|
"service.name", Name, |
||||||
|
"service.version", Version, |
||||||
|
"trace_id", log.TraceID(), |
||||||
|
"span_id", log.SpanID(), |
||||||
|
) |
||||||
|
c := config.New( |
||||||
|
config.WithSource( |
||||||
|
file.NewSource(flagconf), |
||||||
|
), |
||||||
|
) |
||||||
|
if err := c.Load(); err != nil { |
||||||
|
panic(err) |
||||||
|
} |
||||||
|
|
||||||
|
var bc conf.Bootstrap |
||||||
|
if err := c.Scan(&bc); err != nil { |
||||||
|
panic(err) |
||||||
|
} |
||||||
|
|
||||||
|
app, cleanup, err := initApp(bc.Server, bc.Data, logger) |
||||||
|
if err != nil { |
||||||
|
panic(err) |
||||||
|
} |
||||||
|
defer cleanup() |
||||||
|
|
||||||
|
// start and wait for stop signal
|
||||||
|
if err := app.Run(); err != nil { |
||||||
|
panic(err) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
// +build wireinject
|
||||||
|
|
||||||
|
// The build tag makes sure the stub is not built in the final build.
|
||||||
|
|
||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/biz" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/conf" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/data" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/server" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/service" |
||||||
|
"github.com/go-kratos/kratos/v2" |
||||||
|
"github.com/go-kratos/kratos/v2/log" |
||||||
|
"github.com/google/wire" |
||||||
|
) |
||||||
|
|
||||||
|
// initApp init kratos application.
|
||||||
|
func initApp(*conf.Server, *conf.Data, log.Logger) (*kratos.App, func(), error) { |
||||||
|
panic(wire.Build(server.ProviderSet, data.ProviderSet, biz.ProviderSet, service.ProviderSet, newApp)) |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
// Code generated by Wire. DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:generate go run github.com/google/wire/cmd/wire
|
||||||
|
//+build !wireinject
|
||||||
|
|
||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/biz" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/conf" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/data" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/server" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/service" |
||||||
|
"github.com/go-kratos/kratos/v2" |
||||||
|
"github.com/go-kratos/kratos/v2/log" |
||||||
|
) |
||||||
|
|
||||||
|
// Injectors from wire.go:
|
||||||
|
|
||||||
|
// initApp init kratos application.
|
||||||
|
func initApp(confServer *conf.Server, confData *conf.Data, logger log.Logger) (*kratos.App, func(), error) { |
||||||
|
dataData, cleanup, err := data.NewData(confData, logger) |
||||||
|
if err != nil { |
||||||
|
return nil, nil, err |
||||||
|
} |
||||||
|
greeterRepo := data.NewGreeterRepo(dataData, logger) |
||||||
|
greeterUsecase := biz.NewGreeterUsecase(greeterRepo, logger) |
||||||
|
greeterService := service.NewGreeterService(greeterUsecase, logger) |
||||||
|
httpServer := server.NewHTTPServer(confServer, greeterService, logger) |
||||||
|
grpcServer := server.NewGRPCServer(confServer, greeterService, logger) |
||||||
|
app := newApp(logger, httpServer, grpcServer) |
||||||
|
return app, func() { |
||||||
|
cleanup() |
||||||
|
}, nil |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
server: |
||||||
|
http: |
||||||
|
addr: 0.0.0.0:8000 |
||||||
|
timeout: 1s |
||||||
|
grpc: |
||||||
|
addr: 0.0.0.0:9000 |
||||||
|
timeout: 1s |
||||||
|
data: |
||||||
|
database: |
||||||
|
driver: mysql |
||||||
|
source: root:root@tcp(127.0.0.1:3306)/test |
||||||
|
redis: |
||||||
|
addr: 127.0.0.1:6379 |
||||||
|
read_timeout: 0.2s |
||||||
|
write_timeout: 0.2s |
@ -0,0 +1,3 @@ |
|||||||
|
package generate |
||||||
|
|
||||||
|
//go:generate kratos proto client api
|
@ -0,0 +1 @@ |
|||||||
|
# Biz |
@ -0,0 +1,6 @@ |
|||||||
|
package biz |
||||||
|
|
||||||
|
import "github.com/google/wire" |
||||||
|
|
||||||
|
// ProviderSet is biz providers.
|
||||||
|
var ProviderSet = wire.NewSet(NewGreeterUsecase) |
@ -0,0 +1,32 @@ |
|||||||
|
package biz |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"github.com/go-kratos/kratos/v2/log" |
||||||
|
) |
||||||
|
|
||||||
|
type Greeter struct { |
||||||
|
Hello string |
||||||
|
} |
||||||
|
|
||||||
|
type GreeterRepo interface { |
||||||
|
CreateGreeter(context.Context, *Greeter) error |
||||||
|
UpdateGreeter(context.Context, *Greeter) error |
||||||
|
} |
||||||
|
|
||||||
|
type GreeterUsecase struct { |
||||||
|
repo GreeterRepo |
||||||
|
log *log.Helper |
||||||
|
} |
||||||
|
|
||||||
|
func NewGreeterUsecase(repo GreeterRepo, logger log.Logger) *GreeterUsecase { |
||||||
|
return &GreeterUsecase{repo: repo, log: log.NewHelper(logger)} |
||||||
|
} |
||||||
|
|
||||||
|
func (uc *GreeterUsecase) Create(ctx context.Context, g *Greeter) error { |
||||||
|
return uc.repo.CreateGreeter(ctx, g) |
||||||
|
} |
||||||
|
|
||||||
|
func (uc *GreeterUsecase) Update(ctx context.Context, g *Greeter) error { |
||||||
|
return uc.repo.UpdateGreeter(ctx, g) |
||||||
|
} |
@ -0,0 +1,653 @@ |
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.26.0
|
||||||
|
// protoc v3.15.7
|
||||||
|
// source: internal/conf/conf.proto
|
||||||
|
|
||||||
|
package conf |
||||||
|
|
||||||
|
import ( |
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect" |
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl" |
||||||
|
durationpb "google.golang.org/protobuf/types/known/durationpb" |
||||||
|
reflect "reflect" |
||||||
|
sync "sync" |
||||||
|
) |
||||||
|
|
||||||
|
const ( |
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) |
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) |
||||||
|
) |
||||||
|
|
||||||
|
type Bootstrap struct { |
||||||
|
state protoimpl.MessageState |
||||||
|
sizeCache protoimpl.SizeCache |
||||||
|
unknownFields protoimpl.UnknownFields |
||||||
|
|
||||||
|
Server *Server `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` |
||||||
|
Data *Data `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Bootstrap) Reset() { |
||||||
|
*x = Bootstrap{} |
||||||
|
if protoimpl.UnsafeEnabled { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[0] |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Bootstrap) String() string { |
||||||
|
return protoimpl.X.MessageStringOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
func (*Bootstrap) ProtoMessage() {} |
||||||
|
|
||||||
|
func (x *Bootstrap) ProtoReflect() protoreflect.Message { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[0] |
||||||
|
if protoimpl.UnsafeEnabled && x != nil { |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
if ms.LoadMessageInfo() == nil { |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
return ms |
||||||
|
} |
||||||
|
return mi.MessageOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use Bootstrap.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Bootstrap) Descriptor() ([]byte, []int) { |
||||||
|
return file_internal_conf_conf_proto_rawDescGZIP(), []int{0} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Bootstrap) GetServer() *Server { |
||||||
|
if x != nil { |
||||||
|
return x.Server |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Bootstrap) GetData() *Data { |
||||||
|
if x != nil { |
||||||
|
return x.Data |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
type Server struct { |
||||||
|
state protoimpl.MessageState |
||||||
|
sizeCache protoimpl.SizeCache |
||||||
|
unknownFields protoimpl.UnknownFields |
||||||
|
|
||||||
|
Http *Server_HTTP `protobuf:"bytes,1,opt,name=http,proto3" json:"http,omitempty"` |
||||||
|
Grpc *Server_GRPC `protobuf:"bytes,2,opt,name=grpc,proto3" json:"grpc,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server) Reset() { |
||||||
|
*x = Server{} |
||||||
|
if protoimpl.UnsafeEnabled { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[1] |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server) String() string { |
||||||
|
return protoimpl.X.MessageStringOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
func (*Server) ProtoMessage() {} |
||||||
|
|
||||||
|
func (x *Server) ProtoReflect() protoreflect.Message { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[1] |
||||||
|
if protoimpl.UnsafeEnabled && x != nil { |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
if ms.LoadMessageInfo() == nil { |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
return ms |
||||||
|
} |
||||||
|
return mi.MessageOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use Server.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Server) Descriptor() ([]byte, []int) { |
||||||
|
return file_internal_conf_conf_proto_rawDescGZIP(), []int{1} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server) GetHttp() *Server_HTTP { |
||||||
|
if x != nil { |
||||||
|
return x.Http |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server) GetGrpc() *Server_GRPC { |
||||||
|
if x != nil { |
||||||
|
return x.Grpc |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
type Data struct { |
||||||
|
state protoimpl.MessageState |
||||||
|
sizeCache protoimpl.SizeCache |
||||||
|
unknownFields protoimpl.UnknownFields |
||||||
|
|
||||||
|
Database *Data_Database `protobuf:"bytes,1,opt,name=database,proto3" json:"database,omitempty"` |
||||||
|
Redis *Data_Redis `protobuf:"bytes,2,opt,name=redis,proto3" json:"redis,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data) Reset() { |
||||||
|
*x = Data{} |
||||||
|
if protoimpl.UnsafeEnabled { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[2] |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data) String() string { |
||||||
|
return protoimpl.X.MessageStringOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
func (*Data) ProtoMessage() {} |
||||||
|
|
||||||
|
func (x *Data) ProtoReflect() protoreflect.Message { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[2] |
||||||
|
if protoimpl.UnsafeEnabled && x != nil { |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
if ms.LoadMessageInfo() == nil { |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
return ms |
||||||
|
} |
||||||
|
return mi.MessageOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use Data.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Data) Descriptor() ([]byte, []int) { |
||||||
|
return file_internal_conf_conf_proto_rawDescGZIP(), []int{2} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data) GetDatabase() *Data_Database { |
||||||
|
if x != nil { |
||||||
|
return x.Database |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data) GetRedis() *Data_Redis { |
||||||
|
if x != nil { |
||||||
|
return x.Redis |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
type Server_HTTP struct { |
||||||
|
state protoimpl.MessageState |
||||||
|
sizeCache protoimpl.SizeCache |
||||||
|
unknownFields protoimpl.UnknownFields |
||||||
|
|
||||||
|
Network string `protobuf:"bytes,1,opt,name=network,proto3" json:"network,omitempty"` |
||||||
|
Addr string `protobuf:"bytes,2,opt,name=addr,proto3" json:"addr,omitempty"` |
||||||
|
Timeout *durationpb.Duration `protobuf:"bytes,3,opt,name=timeout,proto3" json:"timeout,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_HTTP) Reset() { |
||||||
|
*x = Server_HTTP{} |
||||||
|
if protoimpl.UnsafeEnabled { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[3] |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_HTTP) String() string { |
||||||
|
return protoimpl.X.MessageStringOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
func (*Server_HTTP) ProtoMessage() {} |
||||||
|
|
||||||
|
func (x *Server_HTTP) ProtoReflect() protoreflect.Message { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[3] |
||||||
|
if protoimpl.UnsafeEnabled && x != nil { |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
if ms.LoadMessageInfo() == nil { |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
return ms |
||||||
|
} |
||||||
|
return mi.MessageOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use Server_HTTP.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Server_HTTP) Descriptor() ([]byte, []int) { |
||||||
|
return file_internal_conf_conf_proto_rawDescGZIP(), []int{1, 0} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_HTTP) GetNetwork() string { |
||||||
|
if x != nil { |
||||||
|
return x.Network |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_HTTP) GetAddr() string { |
||||||
|
if x != nil { |
||||||
|
return x.Addr |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_HTTP) GetTimeout() *durationpb.Duration { |
||||||
|
if x != nil { |
||||||
|
return x.Timeout |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
type Server_GRPC struct { |
||||||
|
state protoimpl.MessageState |
||||||
|
sizeCache protoimpl.SizeCache |
||||||
|
unknownFields protoimpl.UnknownFields |
||||||
|
|
||||||
|
Network string `protobuf:"bytes,1,opt,name=network,proto3" json:"network,omitempty"` |
||||||
|
Addr string `protobuf:"bytes,2,opt,name=addr,proto3" json:"addr,omitempty"` |
||||||
|
Timeout *durationpb.Duration `protobuf:"bytes,3,opt,name=timeout,proto3" json:"timeout,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_GRPC) Reset() { |
||||||
|
*x = Server_GRPC{} |
||||||
|
if protoimpl.UnsafeEnabled { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[4] |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_GRPC) String() string { |
||||||
|
return protoimpl.X.MessageStringOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
func (*Server_GRPC) ProtoMessage() {} |
||||||
|
|
||||||
|
func (x *Server_GRPC) ProtoReflect() protoreflect.Message { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[4] |
||||||
|
if protoimpl.UnsafeEnabled && x != nil { |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
if ms.LoadMessageInfo() == nil { |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
return ms |
||||||
|
} |
||||||
|
return mi.MessageOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use Server_GRPC.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Server_GRPC) Descriptor() ([]byte, []int) { |
||||||
|
return file_internal_conf_conf_proto_rawDescGZIP(), []int{1, 1} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_GRPC) GetNetwork() string { |
||||||
|
if x != nil { |
||||||
|
return x.Network |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_GRPC) GetAddr() string { |
||||||
|
if x != nil { |
||||||
|
return x.Addr |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Server_GRPC) GetTimeout() *durationpb.Duration { |
||||||
|
if x != nil { |
||||||
|
return x.Timeout |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
type Data_Database struct { |
||||||
|
state protoimpl.MessageState |
||||||
|
sizeCache protoimpl.SizeCache |
||||||
|
unknownFields protoimpl.UnknownFields |
||||||
|
|
||||||
|
Driver string `protobuf:"bytes,1,opt,name=driver,proto3" json:"driver,omitempty"` |
||||||
|
Source string `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Database) Reset() { |
||||||
|
*x = Data_Database{} |
||||||
|
if protoimpl.UnsafeEnabled { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[5] |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Database) String() string { |
||||||
|
return protoimpl.X.MessageStringOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
func (*Data_Database) ProtoMessage() {} |
||||||
|
|
||||||
|
func (x *Data_Database) ProtoReflect() protoreflect.Message { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[5] |
||||||
|
if protoimpl.UnsafeEnabled && x != nil { |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
if ms.LoadMessageInfo() == nil { |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
return ms |
||||||
|
} |
||||||
|
return mi.MessageOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use Data_Database.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Data_Database) Descriptor() ([]byte, []int) { |
||||||
|
return file_internal_conf_conf_proto_rawDescGZIP(), []int{2, 0} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Database) GetDriver() string { |
||||||
|
if x != nil { |
||||||
|
return x.Driver |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Database) GetSource() string { |
||||||
|
if x != nil { |
||||||
|
return x.Source |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
type Data_Redis struct { |
||||||
|
state protoimpl.MessageState |
||||||
|
sizeCache protoimpl.SizeCache |
||||||
|
unknownFields protoimpl.UnknownFields |
||||||
|
|
||||||
|
Network string `protobuf:"bytes,1,opt,name=network,proto3" json:"network,omitempty"` |
||||||
|
Addr string `protobuf:"bytes,2,opt,name=addr,proto3" json:"addr,omitempty"` |
||||||
|
ReadTimeout *durationpb.Duration `protobuf:"bytes,3,opt,name=read_timeout,json=readTimeout,proto3" json:"read_timeout,omitempty"` |
||||||
|
WriteTimeout *durationpb.Duration `protobuf:"bytes,4,opt,name=write_timeout,json=writeTimeout,proto3" json:"write_timeout,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Redis) Reset() { |
||||||
|
*x = Data_Redis{} |
||||||
|
if protoimpl.UnsafeEnabled { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[6] |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Redis) String() string { |
||||||
|
return protoimpl.X.MessageStringOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
func (*Data_Redis) ProtoMessage() {} |
||||||
|
|
||||||
|
func (x *Data_Redis) ProtoReflect() protoreflect.Message { |
||||||
|
mi := &file_internal_conf_conf_proto_msgTypes[6] |
||||||
|
if protoimpl.UnsafeEnabled && x != nil { |
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
||||||
|
if ms.LoadMessageInfo() == nil { |
||||||
|
ms.StoreMessageInfo(mi) |
||||||
|
} |
||||||
|
return ms |
||||||
|
} |
||||||
|
return mi.MessageOf(x) |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated: Use Data_Redis.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Data_Redis) Descriptor() ([]byte, []int) { |
||||||
|
return file_internal_conf_conf_proto_rawDescGZIP(), []int{2, 1} |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Redis) GetNetwork() string { |
||||||
|
if x != nil { |
||||||
|
return x.Network |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Redis) GetAddr() string { |
||||||
|
if x != nil { |
||||||
|
return x.Addr |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Redis) GetReadTimeout() *durationpb.Duration { |
||||||
|
if x != nil { |
||||||
|
return x.ReadTimeout |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (x *Data_Redis) GetWriteTimeout() *durationpb.Duration { |
||||||
|
if x != nil { |
||||||
|
return x.WriteTimeout |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
var File_internal_conf_conf_proto protoreflect.FileDescriptor |
||||||
|
|
||||||
|
var file_internal_conf_conf_proto_rawDesc = []byte{ |
||||||
|
0x0a, 0x18, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x2f, |
||||||
|
0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x6b, 0x72, 0x61, 0x74, |
||||||
|
0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, |
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, |
||||||
|
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, |
||||||
|
0x72, 0x61, 0x70, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, |
||||||
|
0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, |
||||||
|
0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, |
||||||
|
0x24, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, |
||||||
|
0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, |
||||||
|
0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xb8, 0x02, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, |
||||||
|
0x12, 0x2b, 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, |
||||||
|
0x2e, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, |
||||||
|
0x65, 0x72, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, 0x2b, 0x0a, |
||||||
|
0x04, 0x67, 0x72, 0x70, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6b, 0x72, |
||||||
|
0x61, 0x74, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, |
||||||
|
0x47, 0x52, 0x50, 0x43, 0x52, 0x04, 0x67, 0x72, 0x70, 0x63, 0x1a, 0x69, 0x0a, 0x04, 0x48, 0x54, |
||||||
|
0x54, 0x50, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, |
||||||
|
0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, |
||||||
|
0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, |
||||||
|
0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, |
||||||
|
0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, |
||||||
|
0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, |
||||||
|
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x1a, 0x69, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x18, 0x0a, |
||||||
|
0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, |
||||||
|
0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, |
||||||
|
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x74, |
||||||
|
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, |
||||||
|
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, |
||||||
|
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, |
||||||
|
0x22, 0xdd, 0x02, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x61, 0x74, |
||||||
|
0x61, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6b, 0x72, |
||||||
|
0x61, 0x74, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, |
||||||
|
0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, |
||||||
|
0x12, 0x2c, 0x0a, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, |
||||||
|
0x16, 0x2e, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x61, 0x74, |
||||||
|
0x61, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, 0x52, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x1a, 0x3a, |
||||||
|
0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x72, |
||||||
|
0x69, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, 0x69, 0x76, |
||||||
|
0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, |
||||||
|
0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, 0xb3, 0x01, 0x0a, 0x05, 0x52, |
||||||
|
0x65, 0x64, 0x69, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, |
||||||
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12, |
||||||
|
0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, |
||||||
|
0x64, 0x72, 0x12, 0x3c, 0x0a, 0x0c, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, |
||||||
|
0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, |
||||||
|
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, |
||||||
|
0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, |
||||||
|
0x12, 0x3e, 0x0a, 0x0d, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, |
||||||
|
0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, |
||||||
|
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, |
||||||
|
0x6f, 0x6e, 0x52, 0x0c, 0x77, 0x72, 0x69, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, |
||||||
|
0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, |
||||||
|
0x6f, 0x2d, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2d, |
||||||
|
0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, |
||||||
|
0x63, 0x6f, 0x6e, 0x66, 0x3b, 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, |
||||||
|
0x33, |
||||||
|
} |
||||||
|
|
||||||
|
var ( |
||||||
|
file_internal_conf_conf_proto_rawDescOnce sync.Once |
||||||
|
file_internal_conf_conf_proto_rawDescData = file_internal_conf_conf_proto_rawDesc |
||||||
|
) |
||||||
|
|
||||||
|
func file_internal_conf_conf_proto_rawDescGZIP() []byte { |
||||||
|
file_internal_conf_conf_proto_rawDescOnce.Do(func() { |
||||||
|
file_internal_conf_conf_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_conf_conf_proto_rawDescData) |
||||||
|
}) |
||||||
|
return file_internal_conf_conf_proto_rawDescData |
||||||
|
} |
||||||
|
|
||||||
|
var file_internal_conf_conf_proto_msgTypes = make([]protoimpl.MessageInfo, 7) |
||||||
|
var file_internal_conf_conf_proto_goTypes = []interface{}{ |
||||||
|
(*Bootstrap)(nil), // 0: kratos.api.Bootstrap
|
||||||
|
(*Server)(nil), // 1: kratos.api.Server
|
||||||
|
(*Data)(nil), // 2: kratos.api.Data
|
||||||
|
(*Server_HTTP)(nil), // 3: kratos.api.Server.HTTP
|
||||||
|
(*Server_GRPC)(nil), // 4: kratos.api.Server.GRPC
|
||||||
|
(*Data_Database)(nil), // 5: kratos.api.Data.Database
|
||||||
|
(*Data_Redis)(nil), // 6: kratos.api.Data.Redis
|
||||||
|
(*durationpb.Duration)(nil), // 7: google.protobuf.Duration
|
||||||
|
} |
||||||
|
var file_internal_conf_conf_proto_depIdxs = []int32{ |
||||||
|
1, // 0: kratos.api.Bootstrap.server:type_name -> kratos.api.Server
|
||||||
|
2, // 1: kratos.api.Bootstrap.data:type_name -> kratos.api.Data
|
||||||
|
3, // 2: kratos.api.Server.http:type_name -> kratos.api.Server.HTTP
|
||||||
|
4, // 3: kratos.api.Server.grpc:type_name -> kratos.api.Server.GRPC
|
||||||
|
5, // 4: kratos.api.Data.database:type_name -> kratos.api.Data.Database
|
||||||
|
6, // 5: kratos.api.Data.redis:type_name -> kratos.api.Data.Redis
|
||||||
|
7, // 6: kratos.api.Server.HTTP.timeout:type_name -> google.protobuf.Duration
|
||||||
|
7, // 7: kratos.api.Server.GRPC.timeout:type_name -> google.protobuf.Duration
|
||||||
|
7, // 8: kratos.api.Data.Redis.read_timeout:type_name -> google.protobuf.Duration
|
||||||
|
7, // 9: kratos.api.Data.Redis.write_timeout:type_name -> google.protobuf.Duration
|
||||||
|
10, // [10:10] is the sub-list for method output_type
|
||||||
|
10, // [10:10] is the sub-list for method input_type
|
||||||
|
10, // [10:10] is the sub-list for extension type_name
|
||||||
|
10, // [10:10] is the sub-list for extension extendee
|
||||||
|
0, // [0:10] is the sub-list for field type_name
|
||||||
|
} |
||||||
|
|
||||||
|
func init() { file_internal_conf_conf_proto_init() } |
||||||
|
func file_internal_conf_conf_proto_init() { |
||||||
|
if File_internal_conf_conf_proto != nil { |
||||||
|
return |
||||||
|
} |
||||||
|
if !protoimpl.UnsafeEnabled { |
||||||
|
file_internal_conf_conf_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { |
||||||
|
switch v := v.(*Bootstrap); i { |
||||||
|
case 0: |
||||||
|
return &v.state |
||||||
|
case 1: |
||||||
|
return &v.sizeCache |
||||||
|
case 2: |
||||||
|
return &v.unknownFields |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
file_internal_conf_conf_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { |
||||||
|
switch v := v.(*Server); i { |
||||||
|
case 0: |
||||||
|
return &v.state |
||||||
|
case 1: |
||||||
|
return &v.sizeCache |
||||||
|
case 2: |
||||||
|
return &v.unknownFields |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
file_internal_conf_conf_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { |
||||||
|
switch v := v.(*Data); i { |
||||||
|
case 0: |
||||||
|
return &v.state |
||||||
|
case 1: |
||||||
|
return &v.sizeCache |
||||||
|
case 2: |
||||||
|
return &v.unknownFields |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
file_internal_conf_conf_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { |
||||||
|
switch v := v.(*Server_HTTP); i { |
||||||
|
case 0: |
||||||
|
return &v.state |
||||||
|
case 1: |
||||||
|
return &v.sizeCache |
||||||
|
case 2: |
||||||
|
return &v.unknownFields |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
file_internal_conf_conf_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { |
||||||
|
switch v := v.(*Server_GRPC); i { |
||||||
|
case 0: |
||||||
|
return &v.state |
||||||
|
case 1: |
||||||
|
return &v.sizeCache |
||||||
|
case 2: |
||||||
|
return &v.unknownFields |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
file_internal_conf_conf_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { |
||||||
|
switch v := v.(*Data_Database); i { |
||||||
|
case 0: |
||||||
|
return &v.state |
||||||
|
case 1: |
||||||
|
return &v.sizeCache |
||||||
|
case 2: |
||||||
|
return &v.unknownFields |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
file_internal_conf_conf_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { |
||||||
|
switch v := v.(*Data_Redis); i { |
||||||
|
case 0: |
||||||
|
return &v.state |
||||||
|
case 1: |
||||||
|
return &v.sizeCache |
||||||
|
case 2: |
||||||
|
return &v.unknownFields |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
type x struct{} |
||||||
|
out := protoimpl.TypeBuilder{ |
||||||
|
File: protoimpl.DescBuilder{ |
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), |
||||||
|
RawDescriptor: file_internal_conf_conf_proto_rawDesc, |
||||||
|
NumEnums: 0, |
||||||
|
NumMessages: 7, |
||||||
|
NumExtensions: 0, |
||||||
|
NumServices: 0, |
||||||
|
}, |
||||||
|
GoTypes: file_internal_conf_conf_proto_goTypes, |
||||||
|
DependencyIndexes: file_internal_conf_conf_proto_depIdxs, |
||||||
|
MessageInfos: file_internal_conf_conf_proto_msgTypes, |
||||||
|
}.Build() |
||||||
|
File_internal_conf_conf_proto = out.File |
||||||
|
file_internal_conf_conf_proto_rawDesc = nil |
||||||
|
file_internal_conf_conf_proto_goTypes = nil |
||||||
|
file_internal_conf_conf_proto_depIdxs = nil |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
syntax = "proto3"; |
||||||
|
package kratos.api; |
||||||
|
|
||||||
|
option go_package = "github.com/go-kratos/kratos/examples/i18n/internal/conf;conf"; |
||||||
|
|
||||||
|
import "google/protobuf/duration.proto"; |
||||||
|
|
||||||
|
message Bootstrap { |
||||||
|
Server server = 1; |
||||||
|
Data data = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message Server { |
||||||
|
message HTTP { |
||||||
|
string network = 1; |
||||||
|
string addr = 2; |
||||||
|
google.protobuf.Duration timeout = 3; |
||||||
|
} |
||||||
|
message GRPC { |
||||||
|
string network = 1; |
||||||
|
string addr = 2; |
||||||
|
google.protobuf.Duration timeout = 3; |
||||||
|
} |
||||||
|
HTTP http = 1; |
||||||
|
GRPC grpc = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message Data { |
||||||
|
message Database { |
||||||
|
string driver = 1; |
||||||
|
string source = 2; |
||||||
|
} |
||||||
|
message Redis { |
||||||
|
string network = 1; |
||||||
|
string addr = 2; |
||||||
|
google.protobuf.Duration read_timeout = 3; |
||||||
|
google.protobuf.Duration write_timeout = 4; |
||||||
|
} |
||||||
|
Database database = 1; |
||||||
|
Redis redis = 2; |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
# Data |
@ -0,0 +1,23 @@ |
|||||||
|
package data |
||||||
|
|
||||||
|
import ( |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/conf" |
||||||
|
"github.com/go-kratos/kratos/v2/log" |
||||||
|
"github.com/google/wire" |
||||||
|
) |
||||||
|
|
||||||
|
// ProviderSet is data providers.
|
||||||
|
var ProviderSet = wire.NewSet(NewData, NewGreeterRepo) |
||||||
|
|
||||||
|
// Data .
|
||||||
|
type Data struct { |
||||||
|
// TODO warpped database client
|
||||||
|
} |
||||||
|
|
||||||
|
// NewData .
|
||||||
|
func NewData(c *conf.Data, logger log.Logger) (*Data, func(), error) { |
||||||
|
cleanup := func() { |
||||||
|
logger.Log(log.LevelInfo, "closing the data resources") |
||||||
|
} |
||||||
|
return &Data{}, cleanup, nil |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package data |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/biz" |
||||||
|
"github.com/go-kratos/kratos/v2/log" |
||||||
|
) |
||||||
|
|
||||||
|
type greeterRepo struct { |
||||||
|
data *Data |
||||||
|
log *log.Helper |
||||||
|
} |
||||||
|
|
||||||
|
// NewGreeterRepo .
|
||||||
|
func NewGreeterRepo(data *Data, logger log.Logger) biz.GreeterRepo { |
||||||
|
return &greeterRepo{ |
||||||
|
data: data, |
||||||
|
log: log.NewHelper(logger), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (r *greeterRepo) CreateGreeter(ctx context.Context, g *biz.Greeter) error { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (r *greeterRepo) UpdateGreeter(ctx context.Context, g *biz.Greeter) error { |
||||||
|
return nil |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
package localize |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"github.com/BurntSushi/toml" |
||||||
|
"github.com/nicksnyder/go-i18n/v2/i18n" |
||||||
|
"golang.org/x/text/language" |
||||||
|
|
||||||
|
"github.com/go-kratos/kratos/v2/middleware" |
||||||
|
"github.com/go-kratos/kratos/v2/transport" |
||||||
|
) |
||||||
|
|
||||||
|
type localizerKey struct{} |
||||||
|
|
||||||
|
func I18N() middleware.Middleware { |
||||||
|
bundle := i18n.NewBundle(language.English) |
||||||
|
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) |
||||||
|
bundle.MustLoadMessageFile("../../active.zh.toml") |
||||||
|
|
||||||
|
return func(handler middleware.Handler) middleware.Handler { |
||||||
|
return func(ctx context.Context, req interface{}) (reply interface{}, err error) { |
||||||
|
if tr, ok := transport.FromServerContext(ctx); ok { |
||||||
|
accept := tr.RequestHeader().Get("accept-language") |
||||||
|
println(accept) |
||||||
|
localizer := i18n.NewLocalizer(bundle, accept) |
||||||
|
ctx = context.WithValue(ctx, localizerKey{}, localizer) |
||||||
|
} |
||||||
|
return handler(ctx, req) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func FromContext(ctx context.Context) *i18n.Localizer { |
||||||
|
return ctx.Value(localizerKey{}).(*i18n.Localizer) |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
package server |
||||||
|
|
||||||
|
import ( |
||||||
|
v1 "github.com/go-kratos/kratos/examples/i18n/api/helloworld/v1" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/conf" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/service" |
||||||
|
"github.com/go-kratos/kratos/v2/log" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/logging" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/metrics" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/recovery" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/tracing" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/validate" |
||||||
|
"github.com/go-kratos/kratos/v2/transport/grpc" |
||||||
|
) |
||||||
|
|
||||||
|
// NewGRPCServer new a gRPC server.
|
||||||
|
func NewGRPCServer(c *conf.Server, greeter *service.GreeterService, logger log.Logger) *grpc.Server { |
||||||
|
var opts = []grpc.ServerOption{ |
||||||
|
grpc.Middleware( |
||||||
|
recovery.Recovery(), |
||||||
|
tracing.Server(), |
||||||
|
logging.Server(logger), |
||||||
|
metrics.Server(), |
||||||
|
validate.Validator(), |
||||||
|
), |
||||||
|
} |
||||||
|
if c.Grpc.Network != "" { |
||||||
|
opts = append(opts, grpc.Network(c.Grpc.Network)) |
||||||
|
} |
||||||
|
if c.Grpc.Addr != "" { |
||||||
|
opts = append(opts, grpc.Address(c.Grpc.Addr)) |
||||||
|
} |
||||||
|
if c.Grpc.Timeout != nil { |
||||||
|
opts = append(opts, grpc.Timeout(c.Grpc.Timeout.AsDuration())) |
||||||
|
} |
||||||
|
srv := grpc.NewServer(opts...) |
||||||
|
v1.RegisterGreeterServer(srv, greeter) |
||||||
|
return srv |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
package server |
||||||
|
|
||||||
|
import ( |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/api/helloworld/v1" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/conf" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/pkg/middleware/localize" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/service" |
||||||
|
"github.com/go-kratos/kratos/v2/log" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/logging" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/metrics" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/recovery" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/tracing" |
||||||
|
"github.com/go-kratos/kratos/v2/middleware/validate" |
||||||
|
"github.com/go-kratos/kratos/v2/transport/http" |
||||||
|
) |
||||||
|
|
||||||
|
// NewHTTPServer new a HTTP server.
|
||||||
|
func NewHTTPServer(c *conf.Server, greeter *service.GreeterService, logger log.Logger) *http.Server { |
||||||
|
var opts = []http.ServerOption{ |
||||||
|
http.Middleware( |
||||||
|
recovery.Recovery(), |
||||||
|
tracing.Server(), |
||||||
|
logging.Server(logger), |
||||||
|
metrics.Server(), |
||||||
|
localize.I18N(), |
||||||
|
validate.Validator(), |
||||||
|
), |
||||||
|
} |
||||||
|
if c.Http.Network != "" { |
||||||
|
opts = append(opts, http.Network(c.Http.Network)) |
||||||
|
} |
||||||
|
if c.Http.Addr != "" { |
||||||
|
opts = append(opts, http.Address(c.Http.Addr)) |
||||||
|
} |
||||||
|
if c.Http.Timeout != nil { |
||||||
|
opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration())) |
||||||
|
} |
||||||
|
srv := http.NewServer(opts...) |
||||||
|
v1.RegisterGreeterHTTPServer(srv, greeter) |
||||||
|
return srv |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package server |
||||||
|
|
||||||
|
import ( |
||||||
|
"github.com/google/wire" |
||||||
|
) |
||||||
|
|
||||||
|
// ProviderSet is server providers.
|
||||||
|
var ProviderSet = wire.NewSet(NewHTTPServer, NewGRPCServer) |
@ -0,0 +1 @@ |
|||||||
|
# Service |
@ -0,0 +1,49 @@ |
|||||||
|
package service |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/pkg/middleware/localize" |
||||||
|
"github.com/nicksnyder/go-i18n/v2/i18n" |
||||||
|
|
||||||
|
"github.com/go-kratos/kratos/examples/i18n/api/helloworld/v1" |
||||||
|
"github.com/go-kratos/kratos/examples/i18n/internal/biz" |
||||||
|
"github.com/go-kratos/kratos/v2/log" |
||||||
|
) |
||||||
|
|
||||||
|
// GreeterService is a greeter service.
|
||||||
|
type GreeterService struct { |
||||||
|
v1.UnimplementedGreeterServer |
||||||
|
|
||||||
|
uc *biz.GreeterUsecase |
||||||
|
log *log.Helper |
||||||
|
} |
||||||
|
|
||||||
|
// NewGreeterService new a greeter service.
|
||||||
|
func NewGreeterService(uc *biz.GreeterUsecase, logger log.Logger) *GreeterService { |
||||||
|
return &GreeterService{uc: uc, log: log.NewHelper(logger)} |
||||||
|
} |
||||||
|
|
||||||
|
// SayHello implements helloworld.GreeterServer
|
||||||
|
func (s *GreeterService) SayHello(ctx context.Context, in *v1.HelloRequest) (*v1.HelloReply, error) { |
||||||
|
s.log.WithContext(ctx).Infof("SayHello Received: %v", in.GetName()) |
||||||
|
|
||||||
|
if in.GetName() == "error" { |
||||||
|
return nil, v1.ErrorUserNotFound("user not found: %s", in.GetName()) |
||||||
|
} |
||||||
|
localizer := localize.FromContext(ctx) |
||||||
|
helloMsg, err := localizer.Localize(&i18n.LocalizeConfig{ |
||||||
|
DefaultMessage: &i18n.Message{ |
||||||
|
Description: "sayhello", |
||||||
|
ID: "sayHello", |
||||||
|
One: "Hello {{.Name}}", |
||||||
|
Other: "Hello {{.Name}}", |
||||||
|
}, |
||||||
|
TemplateData: map[string]interface{}{ |
||||||
|
"Name": in.Name, |
||||||
|
}, |
||||||
|
}) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
return &v1.HelloReply{Message: helloMsg}, nil |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
package service |
||||||
|
|
||||||
|
import "github.com/google/wire" |
||||||
|
|
||||||
|
// ProviderSet is service providers.
|
||||||
|
var ProviderSet = wire.NewSet(NewGreeterService) |
@ -0,0 +1 @@ |
|||||||
|
# third_party |
@ -0,0 +1,18 @@ |
|||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package errors; |
||||||
|
|
||||||
|
option go_package = "github.com/go-kratos/kratos/v2/errors;errors"; |
||||||
|
option java_multiple_files = true; |
||||||
|
option java_package = "com.github.kratos.errors"; |
||||||
|
option objc_class_prefix = "KratosErrors"; |
||||||
|
|
||||||
|
import "google/protobuf/descriptor.proto"; |
||||||
|
|
||||||
|
extend google.protobuf.EnumOptions { |
||||||
|
int32 default_code = 1108; |
||||||
|
} |
||||||
|
|
||||||
|
extend google.protobuf.EnumValueOptions { |
||||||
|
int32 code = 1109; |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
// Copyright (c) 2015, Google Inc. |
||||||
|
// |
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
// you may not use this file except in compliance with the License. |
||||||
|
// You may obtain a copy of the License at |
||||||
|
// |
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
// |
||||||
|
// Unless required by applicable law or agreed to in writing, software |
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
// See the License for the specific language governing permissions and |
||||||
|
// limitations under the License. |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package google.api; |
||||||
|
|
||||||
|
import "google/api/http.proto"; |
||||||
|
import "google/protobuf/descriptor.proto"; |
||||||
|
|
||||||
|
option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; |
||||||
|
option java_multiple_files = true; |
||||||
|
option java_outer_classname = "AnnotationsProto"; |
||||||
|
option java_package = "com.google.api"; |
||||||
|
option objc_class_prefix = "GAPI"; |
||||||
|
|
||||||
|
extend google.protobuf.MethodOptions { |
||||||
|
// See `HttpRule`. |
||||||
|
HttpRule http = 72295728; |
||||||
|
} |
@ -0,0 +1,375 @@ |
|||||||
|
// Copyright 2020 Google LLC |
||||||
|
// |
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
// you may not use this file except in compliance with the License. |
||||||
|
// You may obtain a copy of the License at |
||||||
|
// |
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
// |
||||||
|
// Unless required by applicable law or agreed to in writing, software |
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
// See the License for the specific language governing permissions and |
||||||
|
// limitations under the License. |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package google.api; |
||||||
|
|
||||||
|
option cc_enable_arenas = true; |
||||||
|
option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; |
||||||
|
option java_multiple_files = true; |
||||||
|
option java_outer_classname = "HttpProto"; |
||||||
|
option java_package = "com.google.api"; |
||||||
|
option objc_class_prefix = "GAPI"; |
||||||
|
|
||||||
|
// Defines the HTTP configuration for an API service. It contains a list of |
||||||
|
// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method |
||||||
|
// to one or more HTTP REST API methods. |
||||||
|
message Http { |
||||||
|
// A list of HTTP configuration rules that apply to individual API methods. |
||||||
|
// |
||||||
|
// **NOTE:** All service configuration rules follow "last one wins" order. |
||||||
|
repeated HttpRule rules = 1; |
||||||
|
|
||||||
|
// When set to true, URL path parameters will be fully URI-decoded except in |
||||||
|
// cases of single segment matches in reserved expansion, where "%2F" will be |
||||||
|
// left encoded. |
||||||
|
// |
||||||
|
// The default behavior is to not decode RFC 6570 reserved characters in multi |
||||||
|
// segment matches. |
||||||
|
bool fully_decode_reserved_expansion = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// # gRPC Transcoding |
||||||
|
// |
||||||
|
// gRPC Transcoding is a feature for mapping between a gRPC method and one or |
||||||
|
// more HTTP REST endpoints. It allows developers to build a single API service |
||||||
|
// that supports both gRPC APIs and REST APIs. Many systems, including [Google |
||||||
|
// APIs](https://github.com/googleapis/googleapis), |
||||||
|
// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC |
||||||
|
// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), |
||||||
|
// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature |
||||||
|
// and use it for large scale production services. |
||||||
|
// |
||||||
|
// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies |
||||||
|
// how different portions of the gRPC request message are mapped to the URL |
||||||
|
// path, URL query parameters, and HTTP request body. It also controls how the |
||||||
|
// gRPC response message is mapped to the HTTP response body. `HttpRule` is |
||||||
|
// typically specified as an `google.api.http` annotation on the gRPC method. |
||||||
|
// |
||||||
|
// Each mapping specifies a URL path template and an HTTP method. The path |
||||||
|
// template may refer to one or more fields in the gRPC request message, as long |
||||||
|
// as each field is a non-repeated field with a primitive (non-message) type. |
||||||
|
// The path template controls how fields of the request message are mapped to |
||||||
|
// the URL path. |
||||||
|
// |
||||||
|
// Example: |
||||||
|
// |
||||||
|
// service Messaging { |
||||||
|
// rpc GetMessage(GetMessageRequest) returns (Message) { |
||||||
|
// option (google.api.http) = { |
||||||
|
// get: "/v1/{name=messages/*}" |
||||||
|
// }; |
||||||
|
// } |
||||||
|
// } |
||||||
|
// message GetMessageRequest { |
||||||
|
// string name = 1; // Mapped to URL path. |
||||||
|
// } |
||||||
|
// message Message { |
||||||
|
// string text = 1; // The resource content. |
||||||
|
// } |
||||||
|
// |
||||||
|
// This enables an HTTP REST to gRPC mapping as below: |
||||||
|
// |
||||||
|
// HTTP | gRPC |
||||||
|
// -----|----- |
||||||
|
// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` |
||||||
|
// |
||||||
|
// Any fields in the request message which are not bound by the path template |
||||||
|
// automatically become HTTP query parameters if there is no HTTP request body. |
||||||
|
// For example: |
||||||
|
// |
||||||
|
// service Messaging { |
||||||
|
// rpc GetMessage(GetMessageRequest) returns (Message) { |
||||||
|
// option (google.api.http) = { |
||||||
|
// get:"/v1/messages/{message_id}" |
||||||
|
// }; |
||||||
|
// } |
||||||
|
// } |
||||||
|
// message GetMessageRequest { |
||||||
|
// message SubMessage { |
||||||
|
// string subfield = 1; |
||||||
|
// } |
||||||
|
// string message_id = 1; // Mapped to URL path. |
||||||
|
// int64 revision = 2; // Mapped to URL query parameter `revision`. |
||||||
|
// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. |
||||||
|
// } |
||||||
|
// |
||||||
|
// This enables a HTTP JSON to RPC mapping as below: |
||||||
|
// |
||||||
|
// HTTP | gRPC |
||||||
|
// -----|----- |
||||||
|
// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | |
||||||
|
// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: |
||||||
|
// "foo"))` |
||||||
|
// |
||||||
|
// Note that fields which are mapped to URL query parameters must have a |
||||||
|
// primitive type or a repeated primitive type or a non-repeated message type. |
||||||
|
// In the case of a repeated type, the parameter can be repeated in the URL |
||||||
|
// as `...?param=A¶m=B`. In the case of a message type, each field of the |
||||||
|
// message is mapped to a separate parameter, such as |
||||||
|
// `...?foo.a=A&foo.b=B&foo.c=C`. |
||||||
|
// |
||||||
|
// For HTTP methods that allow a request body, the `body` field |
||||||
|
// specifies the mapping. Consider a REST update method on the |
||||||
|
// message resource collection: |
||||||
|
// |
||||||
|
// service Messaging { |
||||||
|
// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { |
||||||
|
// option (google.api.http) = { |
||||||
|
// patch: "/v1/messages/{message_id}" |
||||||
|
// body: "message" |
||||||
|
// }; |
||||||
|
// } |
||||||
|
// } |
||||||
|
// message UpdateMessageRequest { |
||||||
|
// string message_id = 1; // mapped to the URL |
||||||
|
// Message message = 2; // mapped to the body |
||||||
|
// } |
||||||
|
// |
||||||
|
// The following HTTP JSON to RPC mapping is enabled, where the |
||||||
|
// representation of the JSON in the request body is determined by |
||||||
|
// protos JSON encoding: |
||||||
|
// |
||||||
|
// HTTP | gRPC |
||||||
|
// -----|----- |
||||||
|
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: |
||||||
|
// "123456" message { text: "Hi!" })` |
||||||
|
// |
||||||
|
// The special name `*` can be used in the body mapping to define that |
||||||
|
// every field not bound by the path template should be mapped to the |
||||||
|
// request body. This enables the following alternative definition of |
||||||
|
// the update method: |
||||||
|
// |
||||||
|
// service Messaging { |
||||||
|
// rpc UpdateMessage(Message) returns (Message) { |
||||||
|
// option (google.api.http) = { |
||||||
|
// patch: "/v1/messages/{message_id}" |
||||||
|
// body: "*" |
||||||
|
// }; |
||||||
|
// } |
||||||
|
// } |
||||||
|
// message Message { |
||||||
|
// string message_id = 1; |
||||||
|
// string text = 2; |
||||||
|
// } |
||||||
|
// |
||||||
|
// |
||||||
|
// The following HTTP JSON to RPC mapping is enabled: |
||||||
|
// |
||||||
|
// HTTP | gRPC |
||||||
|
// -----|----- |
||||||
|
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: |
||||||
|
// "123456" text: "Hi!")` |
||||||
|
// |
||||||
|
// Note that when using `*` in the body mapping, it is not possible to |
||||||
|
// have HTTP parameters, as all fields not bound by the path end in |
||||||
|
// the body. This makes this option more rarely used in practice when |
||||||
|
// defining REST APIs. The common usage of `*` is in custom methods |
||||||
|
// which don't use the URL at all for transferring data. |
||||||
|
// |
||||||
|
// It is possible to define multiple HTTP methods for one RPC by using |
||||||
|
// the `additional_bindings` option. Example: |
||||||
|
// |
||||||
|
// service Messaging { |
||||||
|
// rpc GetMessage(GetMessageRequest) returns (Message) { |
||||||
|
// option (google.api.http) = { |
||||||
|
// get: "/v1/messages/{message_id}" |
||||||
|
// additional_bindings { |
||||||
|
// get: "/v1/users/{user_id}/messages/{message_id}" |
||||||
|
// } |
||||||
|
// }; |
||||||
|
// } |
||||||
|
// } |
||||||
|
// message GetMessageRequest { |
||||||
|
// string message_id = 1; |
||||||
|
// string user_id = 2; |
||||||
|
// } |
||||||
|
// |
||||||
|
// This enables the following two alternative HTTP JSON to RPC mappings: |
||||||
|
// |
||||||
|
// HTTP | gRPC |
||||||
|
// -----|----- |
||||||
|
// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` |
||||||
|
// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: |
||||||
|
// "123456")` |
||||||
|
// |
||||||
|
// ## Rules for HTTP mapping |
||||||
|
// |
||||||
|
// 1. Leaf request fields (recursive expansion nested messages in the request |
||||||
|
// message) are classified into three categories: |
||||||
|
// - Fields referred by the path template. They are passed via the URL path. |
||||||
|
// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP |
||||||
|
// request body. |
||||||
|
// - All other fields are passed via the URL query parameters, and the |
||||||
|
// parameter name is the field path in the request message. A repeated |
||||||
|
// field can be represented as multiple query parameters under the same |
||||||
|
// name. |
||||||
|
// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields |
||||||
|
// are passed via URL path and HTTP request body. |
||||||
|
// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all |
||||||
|
// fields are passed via URL path and URL query parameters. |
||||||
|
// |
||||||
|
// ### Path template syntax |
||||||
|
// |
||||||
|
// Template = "/" Segments [ Verb ] ; |
||||||
|
// Segments = Segment { "/" Segment } ; |
||||||
|
// Segment = "*" | "**" | LITERAL | Variable ; |
||||||
|
// Variable = "{" FieldPath [ "=" Segments ] "}" ; |
||||||
|
// FieldPath = IDENT { "." IDENT } ; |
||||||
|
// Verb = ":" LITERAL ; |
||||||
|
// |
||||||
|
// The syntax `*` matches a single URL path segment. The syntax `**` matches |
||||||
|
// zero or more URL path segments, which must be the last part of the URL path |
||||||
|
// except the `Verb`. |
||||||
|
// |
||||||
|
// The syntax `Variable` matches part of the URL path as specified by its |
||||||
|
// template. A variable template must not contain other variables. If a variable |
||||||
|
// matches a single path segment, its template may be omitted, e.g. `{var}` |
||||||
|
// is equivalent to `{var=*}`. |
||||||
|
// |
||||||
|
// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` |
||||||
|
// contains any reserved character, such characters should be percent-encoded |
||||||
|
// before the matching. |
||||||
|
// |
||||||
|
// If a variable contains exactly one path segment, such as `"{var}"` or |
||||||
|
// `"{var=*}"`, when such a variable is expanded into a URL path on the client |
||||||
|
// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The |
||||||
|
// server side does the reverse decoding. Such variables show up in the |
||||||
|
// [Discovery |
||||||
|
// Document](https://developers.google.com/discovery/v1/reference/apis) as |
||||||
|
// `{var}`. |
||||||
|
// |
||||||
|
// If a variable contains multiple path segments, such as `"{var=foo/*}"` |
||||||
|
// or `"{var=**}"`, when such a variable is expanded into a URL path on the |
||||||
|
// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. |
||||||
|
// The server side does the reverse decoding, except "%2F" and "%2f" are left |
||||||
|
// unchanged. Such variables show up in the |
||||||
|
// [Discovery |
||||||
|
// Document](https://developers.google.com/discovery/v1/reference/apis) as |
||||||
|
// `{+var}`. |
||||||
|
// |
||||||
|
// ## Using gRPC API Service Configuration |
||||||
|
// |
||||||
|
// gRPC API Service Configuration (service config) is a configuration language |
||||||
|
// for configuring a gRPC service to become a user-facing product. The |
||||||
|
// service config is simply the YAML representation of the `google.api.Service` |
||||||
|
// proto message. |
||||||
|
// |
||||||
|
// As an alternative to annotating your proto file, you can configure gRPC |
||||||
|
// transcoding in your service config YAML files. You do this by specifying a |
||||||
|
// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same |
||||||
|
// effect as the proto annotation. This can be particularly useful if you |
||||||
|
// have a proto that is reused in multiple services. Note that any transcoding |
||||||
|
// specified in the service config will override any matching transcoding |
||||||
|
// configuration in the proto. |
||||||
|
// |
||||||
|
// Example: |
||||||
|
// |
||||||
|
// http: |
||||||
|
// rules: |
||||||
|
// # Selects a gRPC method and applies HttpRule to it. |
||||||
|
// - selector: example.v1.Messaging.GetMessage |
||||||
|
// get: /v1/messages/{message_id}/{sub.subfield} |
||||||
|
// |
||||||
|
// ## Special notes |
||||||
|
// |
||||||
|
// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the |
||||||
|
// proto to JSON conversion must follow the [proto3 |
||||||
|
// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). |
||||||
|
// |
||||||
|
// While the single segment variable follows the semantics of |
||||||
|
// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String |
||||||
|
// Expansion, the multi segment variable **does not** follow RFC 6570 Section |
||||||
|
// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion |
||||||
|
// does not expand special characters like `?` and `#`, which would lead |
||||||
|
// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding |
||||||
|
// for multi segment variables. |
||||||
|
// |
||||||
|
// The path variables **must not** refer to any repeated or mapped field, |
||||||
|
// because client libraries are not capable of handling such variable expansion. |
||||||
|
// |
||||||
|
// The path variables **must not** capture the leading "/" character. The reason |
||||||
|
// is that the most common use case "{var}" does not capture the leading "/" |
||||||
|
// character. For consistency, all path variables must share the same behavior. |
||||||
|
// |
||||||
|
// Repeated message fields must not be mapped to URL query parameters, because |
||||||
|
// no client library can support such complicated mapping. |
||||||
|
// |
||||||
|
// If an API needs to use a JSON array for request or response body, it can map |
||||||
|
// the request or response body to a repeated field. However, some gRPC |
||||||
|
// Transcoding implementations may not support this feature. |
||||||
|
message HttpRule { |
||||||
|
// Selects a method to which this rule applies. |
||||||
|
// |
||||||
|
// Refer to [selector][google.api.DocumentationRule.selector] for syntax details. |
||||||
|
string selector = 1; |
||||||
|
|
||||||
|
// Determines the URL pattern is matched by this rules. This pattern can be |
||||||
|
// used with any of the {get|put|post|delete|patch} methods. A custom method |
||||||
|
// can be defined using the 'custom' field. |
||||||
|
oneof pattern { |
||||||
|
// Maps to HTTP GET. Used for listing and getting information about |
||||||
|
// resources. |
||||||
|
string get = 2; |
||||||
|
|
||||||
|
// Maps to HTTP PUT. Used for replacing a resource. |
||||||
|
string put = 3; |
||||||
|
|
||||||
|
// Maps to HTTP POST. Used for creating a resource or performing an action. |
||||||
|
string post = 4; |
||||||
|
|
||||||
|
// Maps to HTTP DELETE. Used for deleting a resource. |
||||||
|
string delete = 5; |
||||||
|
|
||||||
|
// Maps to HTTP PATCH. Used for updating a resource. |
||||||
|
string patch = 6; |
||||||
|
|
||||||
|
// The custom pattern is used for specifying an HTTP method that is not |
||||||
|
// included in the `pattern` field, such as HEAD, or "*" to leave the |
||||||
|
// HTTP method unspecified for this rule. The wild-card rule is useful |
||||||
|
// for services that provide content to Web (HTML) clients. |
||||||
|
CustomHttpPattern custom = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// The name of the request field whose value is mapped to the HTTP request |
||||||
|
// body, or `*` for mapping all request fields not captured by the path |
||||||
|
// pattern to the HTTP body, or omitted for not having any HTTP request body. |
||||||
|
// |
||||||
|
// NOTE: the referred field must be present at the top-level of the request |
||||||
|
// message type. |
||||||
|
string body = 7; |
||||||
|
|
||||||
|
// Optional. The name of the response field whose value is mapped to the HTTP |
||||||
|
// response body. When omitted, the entire response message will be used |
||||||
|
// as the HTTP response body. |
||||||
|
// |
||||||
|
// NOTE: The referred field must be present at the top-level of the response |
||||||
|
// message type. |
||||||
|
string response_body = 12; |
||||||
|
|
||||||
|
// Additional HTTP bindings for the selector. Nested bindings must |
||||||
|
// not contain an `additional_bindings` field themselves (that is, |
||||||
|
// the nesting may only be one level deep). |
||||||
|
repeated HttpRule additional_bindings = 11; |
||||||
|
} |
||||||
|
|
||||||
|
// A custom pattern is used for defining custom HTTP verb. |
||||||
|
message CustomHttpPattern { |
||||||
|
// The name of this custom HTTP verb. |
||||||
|
string kind = 1; |
||||||
|
|
||||||
|
// The path matched by this custom verb. |
||||||
|
string path = 2; |
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
// Copyright 2020 Google LLC |
||||||
|
// |
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
// you may not use this file except in compliance with the License. |
||||||
|
// You may obtain a copy of the License at |
||||||
|
// |
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
// |
||||||
|
// Unless required by applicable law or agreed to in writing, software |
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
// See the License for the specific language governing permissions and |
||||||
|
// limitations under the License. |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package google.api; |
||||||
|
|
||||||
|
import "google/protobuf/any.proto"; |
||||||
|
|
||||||
|
option cc_enable_arenas = true; |
||||||
|
option go_package = "google.golang.org/genproto/googleapis/api/httpbody;httpbody"; |
||||||
|
option java_multiple_files = true; |
||||||
|
option java_outer_classname = "HttpBodyProto"; |
||||||
|
option java_package = "com.google.api"; |
||||||
|
option objc_class_prefix = "GAPI"; |
||||||
|
|
||||||
|
// Message that represents an arbitrary HTTP body. It should only be used for |
||||||
|
// payload formats that can't be represented as JSON, such as raw binary or |
||||||
|
// an HTML page. |
||||||
|
// |
||||||
|
// |
||||||
|
// This message can be used both in streaming and non-streaming API methods in |
||||||
|
// the request as well as the response. |
||||||
|
// |
||||||
|
// It can be used as a top-level request field, which is convenient if one |
||||||
|
// wants to extract parameters from either the URL or HTTP template into the |
||||||
|
// request fields and also want access to the raw HTTP body. |
||||||
|
// |
||||||
|
// Example: |
||||||
|
// |
||||||
|
// message GetResourceRequest { |
||||||
|
// // A unique request id. |
||||||
|
// string request_id = 1; |
||||||
|
// |
||||||
|
// // The raw HTTP body is bound to this field. |
||||||
|
// google.api.HttpBody http_body = 2; |
||||||
|
// } |
||||||
|
// |
||||||
|
// service ResourceService { |
||||||
|
// rpc GetResource(GetResourceRequest) returns (google.api.HttpBody); |
||||||
|
// rpc UpdateResource(google.api.HttpBody) returns |
||||||
|
// (google.protobuf.Empty); |
||||||
|
// } |
||||||
|
// |
||||||
|
// Example with streaming methods: |
||||||
|
// |
||||||
|
// service CaldavService { |
||||||
|
// rpc GetCalendar(stream google.api.HttpBody) |
||||||
|
// returns (stream google.api.HttpBody); |
||||||
|
// rpc UpdateCalendar(stream google.api.HttpBody) |
||||||
|
// returns (stream google.api.HttpBody); |
||||||
|
// } |
||||||
|
// |
||||||
|
// Use of this type only changes how the request and response bodies are |
||||||
|
// handled, all other features will continue to work unchanged. |
||||||
|
message HttpBody { |
||||||
|
// The HTTP Content-Type header value specifying the content type of the body. |
||||||
|
string content_type = 1; |
||||||
|
|
||||||
|
// The HTTP request/response body as raw binary. |
||||||
|
bytes data = 2; |
||||||
|
|
||||||
|
// Application specific response metadata. Must be set in the first response |
||||||
|
// for streaming APIs. |
||||||
|
repeated google.protobuf.Any extensions = 3; |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
# protoc-gen-validate (PGV) |
||||||
|
|
||||||
|
* https://github.com/envoyproxy/protoc-gen-validate |
@ -0,0 +1,863 @@ |
|||||||
|
syntax = "proto2"; |
||||||
|
package validate; |
||||||
|
|
||||||
|
option go_package = "github.com/envoyproxy/protoc-gen-validate/validate"; |
||||||
|
option java_package = "io.envoyproxy.pgv.validate"; |
||||||
|
|
||||||
|
import "google/protobuf/descriptor.proto"; |
||||||
|
import "google/protobuf/duration.proto"; |
||||||
|
import "google/protobuf/timestamp.proto"; |
||||||
|
|
||||||
|
// Validation rules applied at the message level |
||||||
|
extend google.protobuf.MessageOptions { |
||||||
|
// Disabled nullifies any validation rules for this message, including any |
||||||
|
// message fields associated with it that do support validation. |
||||||
|
optional bool disabled = 1071; |
||||||
|
// Ignore skips generation of validation methods for this message. |
||||||
|
optional bool ignored = 1072; |
||||||
|
} |
||||||
|
|
||||||
|
// Validation rules applied at the oneof level |
||||||
|
extend google.protobuf.OneofOptions { |
||||||
|
// Required ensures that exactly one the field options in a oneof is set; |
||||||
|
// validation fails if no fields in the oneof are set. |
||||||
|
optional bool required = 1071; |
||||||
|
} |
||||||
|
|
||||||
|
// Validation rules applied at the field level |
||||||
|
extend google.protobuf.FieldOptions { |
||||||
|
// Rules specify the validations to be performed on this field. By default, |
||||||
|
// no validation is performed against a field. |
||||||
|
optional FieldRules rules = 1071; |
||||||
|
} |
||||||
|
|
||||||
|
// FieldRules encapsulates the rules for each type of field. Depending on the |
||||||
|
// field, the correct set should be used to ensure proper validations. |
||||||
|
message FieldRules { |
||||||
|
optional MessageRules message = 17; |
||||||
|
oneof type { |
||||||
|
// Scalar Field Types |
||||||
|
FloatRules float = 1; |
||||||
|
DoubleRules double = 2; |
||||||
|
Int32Rules int32 = 3; |
||||||
|
Int64Rules int64 = 4; |
||||||
|
UInt32Rules uint32 = 5; |
||||||
|
UInt64Rules uint64 = 6; |
||||||
|
SInt32Rules sint32 = 7; |
||||||
|
SInt64Rules sint64 = 8; |
||||||
|
Fixed32Rules fixed32 = 9; |
||||||
|
Fixed64Rules fixed64 = 10; |
||||||
|
SFixed32Rules sfixed32 = 11; |
||||||
|
SFixed64Rules sfixed64 = 12; |
||||||
|
BoolRules bool = 13; |
||||||
|
StringRules string = 14; |
||||||
|
BytesRules bytes = 15; |
||||||
|
|
||||||
|
// Complex Field Types |
||||||
|
EnumRules enum = 16; |
||||||
|
RepeatedRules repeated = 18; |
||||||
|
MapRules map = 19; |
||||||
|
|
||||||
|
// Well-Known Field Types |
||||||
|
AnyRules any = 20; |
||||||
|
DurationRules duration = 21; |
||||||
|
TimestampRules timestamp = 22; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// FloatRules describes the constraints applied to `float` values |
||||||
|
message FloatRules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional float const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional float lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional float lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional float gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional float gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated float in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated float not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// DoubleRules describes the constraints applied to `double` values |
||||||
|
message DoubleRules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional double const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional double lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional double lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional double gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional double gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated double in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated double not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// Int32Rules describes the constraints applied to `int32` values |
||||||
|
message Int32Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional int32 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional int32 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional int32 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional int32 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional int32 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated int32 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated int32 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// Int64Rules describes the constraints applied to `int64` values |
||||||
|
message Int64Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional int64 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional int64 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional int64 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional int64 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional int64 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated int64 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated int64 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// UInt32Rules describes the constraints applied to `uint32` values |
||||||
|
message UInt32Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional uint32 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional uint32 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional uint32 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional uint32 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional uint32 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated uint32 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated uint32 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// UInt64Rules describes the constraints applied to `uint64` values |
||||||
|
message UInt64Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional uint64 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional uint64 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional uint64 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional uint64 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional uint64 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated uint64 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated uint64 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// SInt32Rules describes the constraints applied to `sint32` values |
||||||
|
message SInt32Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional sint32 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional sint32 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional sint32 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional sint32 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional sint32 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated sint32 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated sint32 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// SInt64Rules describes the constraints applied to `sint64` values |
||||||
|
message SInt64Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional sint64 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional sint64 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional sint64 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional sint64 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional sint64 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated sint64 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated sint64 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// Fixed32Rules describes the constraints applied to `fixed32` values |
||||||
|
message Fixed32Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional fixed32 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional fixed32 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional fixed32 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional fixed32 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional fixed32 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated fixed32 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated fixed32 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// Fixed64Rules describes the constraints applied to `fixed64` values |
||||||
|
message Fixed64Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional fixed64 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional fixed64 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional fixed64 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional fixed64 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional fixed64 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated fixed64 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated fixed64 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// SFixed32Rules describes the constraints applied to `sfixed32` values |
||||||
|
message SFixed32Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional sfixed32 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional sfixed32 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional sfixed32 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional sfixed32 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional sfixed32 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated sfixed32 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated sfixed32 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// SFixed64Rules describes the constraints applied to `sfixed64` values |
||||||
|
message SFixed64Rules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional sfixed64 const = 1; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional sfixed64 lt = 2; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than or equal to the |
||||||
|
// specified value, inclusive |
||||||
|
optional sfixed64 lte = 3; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the |
||||||
|
// range is reversed. |
||||||
|
optional sfixed64 gt = 4; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than or equal to the |
||||||
|
// specified value, inclusive. If the value of Gte is larger than a |
||||||
|
// specified Lt or Lte, the range is reversed. |
||||||
|
optional sfixed64 gte = 5; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated sfixed64 in = 6; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated sfixed64 not_in = 7; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// BoolRules describes the constraints applied to `bool` values |
||||||
|
message BoolRules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional bool const = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// StringRules describe the constraints applied to `string` values |
||||||
|
message StringRules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional string const = 1; |
||||||
|
|
||||||
|
// Len specifies that this field must be the specified number of |
||||||
|
// characters (Unicode code points). Note that the number of |
||||||
|
// characters may differ from the number of bytes in the string. |
||||||
|
optional uint64 len = 19; |
||||||
|
|
||||||
|
// MinLen specifies that this field must be the specified number of |
||||||
|
// characters (Unicode code points) at a minimum. Note that the number of |
||||||
|
// characters may differ from the number of bytes in the string. |
||||||
|
optional uint64 min_len = 2; |
||||||
|
|
||||||
|
// MaxLen specifies that this field must be the specified number of |
||||||
|
// characters (Unicode code points) at a maximum. Note that the number of |
||||||
|
// characters may differ from the number of bytes in the string. |
||||||
|
optional uint64 max_len = 3; |
||||||
|
|
||||||
|
// LenBytes specifies that this field must be the specified number of bytes |
||||||
|
// at a minimum |
||||||
|
optional uint64 len_bytes = 20; |
||||||
|
|
||||||
|
// MinBytes specifies that this field must be the specified number of bytes |
||||||
|
// at a minimum |
||||||
|
optional uint64 min_bytes = 4; |
||||||
|
|
||||||
|
// MaxBytes specifies that this field must be the specified number of bytes |
||||||
|
// at a maximum |
||||||
|
optional uint64 max_bytes = 5; |
||||||
|
|
||||||
|
// Pattern specifes that this field must match against the specified |
||||||
|
// regular expression (RE2 syntax). The included expression should elide |
||||||
|
// any delimiters. |
||||||
|
optional string pattern = 6; |
||||||
|
|
||||||
|
// Prefix specifies that this field must have the specified substring at |
||||||
|
// the beginning of the string. |
||||||
|
optional string prefix = 7; |
||||||
|
|
||||||
|
// Suffix specifies that this field must have the specified substring at |
||||||
|
// the end of the string. |
||||||
|
optional string suffix = 8; |
||||||
|
|
||||||
|
// Contains specifies that this field must have the specified substring |
||||||
|
// anywhere in the string. |
||||||
|
optional string contains = 9; |
||||||
|
|
||||||
|
// NotContains specifies that this field cannot have the specified substring |
||||||
|
// anywhere in the string. |
||||||
|
optional string not_contains = 23; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated string in = 10; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated string not_in = 11; |
||||||
|
|
||||||
|
// WellKnown rules provide advanced constraints against common string |
||||||
|
// patterns |
||||||
|
oneof well_known { |
||||||
|
// Email specifies that the field must be a valid email address as |
||||||
|
// defined by RFC 5322 |
||||||
|
bool email = 12; |
||||||
|
|
||||||
|
// Hostname specifies that the field must be a valid hostname as |
||||||
|
// defined by RFC 1034. This constraint does not support |
||||||
|
// internationalized domain names (IDNs). |
||||||
|
bool hostname = 13; |
||||||
|
|
||||||
|
// Ip specifies that the field must be a valid IP (v4 or v6) address. |
||||||
|
// Valid IPv6 addresses should not include surrounding square brackets. |
||||||
|
bool ip = 14; |
||||||
|
|
||||||
|
// Ipv4 specifies that the field must be a valid IPv4 address. |
||||||
|
bool ipv4 = 15; |
||||||
|
|
||||||
|
// Ipv6 specifies that the field must be a valid IPv6 address. Valid |
||||||
|
// IPv6 addresses should not include surrounding square brackets. |
||||||
|
bool ipv6 = 16; |
||||||
|
|
||||||
|
// Uri specifies that the field must be a valid, absolute URI as defined |
||||||
|
// by RFC 3986 |
||||||
|
bool uri = 17; |
||||||
|
|
||||||
|
// UriRef specifies that the field must be a valid URI as defined by RFC |
||||||
|
// 3986 and may be relative or absolute. |
||||||
|
bool uri_ref = 18; |
||||||
|
|
||||||
|
// Address specifies that the field must be either a valid hostname as |
||||||
|
// defined by RFC 1034 (which does not support internationalized domain |
||||||
|
// names or IDNs), or it can be a valid IP (v4 or v6). |
||||||
|
bool address = 21; |
||||||
|
|
||||||
|
// Uuid specifies that the field must be a valid UUID as defined by |
||||||
|
// RFC 4122 |
||||||
|
bool uuid = 22; |
||||||
|
|
||||||
|
// WellKnownRegex specifies a common well known pattern defined as a regex. |
||||||
|
KnownRegex well_known_regex = 24; |
||||||
|
} |
||||||
|
|
||||||
|
// This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable |
||||||
|
// strict header validation. |
||||||
|
// By default, this is true, and HTTP header validations are RFC-compliant. |
||||||
|
// Setting to false will enable a looser validations that only disallows |
||||||
|
// \r\n\0 characters, which can be used to bypass header matching rules. |
||||||
|
optional bool strict = 25 [default = true]; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 26; |
||||||
|
} |
||||||
|
|
||||||
|
// WellKnownRegex contain some well-known patterns. |
||||||
|
enum KnownRegex { |
||||||
|
UNKNOWN = 0; |
||||||
|
|
||||||
|
// HTTP header name as defined by RFC 7230. |
||||||
|
HTTP_HEADER_NAME = 1; |
||||||
|
|
||||||
|
// HTTP header value as defined by RFC 7230. |
||||||
|
HTTP_HEADER_VALUE = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// BytesRules describe the constraints applied to `bytes` values |
||||||
|
message BytesRules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional bytes const = 1; |
||||||
|
|
||||||
|
// Len specifies that this field must be the specified number of bytes |
||||||
|
optional uint64 len = 13; |
||||||
|
|
||||||
|
// MinLen specifies that this field must be the specified number of bytes |
||||||
|
// at a minimum |
||||||
|
optional uint64 min_len = 2; |
||||||
|
|
||||||
|
// MaxLen specifies that this field must be the specified number of bytes |
||||||
|
// at a maximum |
||||||
|
optional uint64 max_len = 3; |
||||||
|
|
||||||
|
// Pattern specifes that this field must match against the specified |
||||||
|
// regular expression (RE2 syntax). The included expression should elide |
||||||
|
// any delimiters. |
||||||
|
optional string pattern = 4; |
||||||
|
|
||||||
|
// Prefix specifies that this field must have the specified bytes at the |
||||||
|
// beginning of the string. |
||||||
|
optional bytes prefix = 5; |
||||||
|
|
||||||
|
// Suffix specifies that this field must have the specified bytes at the |
||||||
|
// end of the string. |
||||||
|
optional bytes suffix = 6; |
||||||
|
|
||||||
|
// Contains specifies that this field must have the specified bytes |
||||||
|
// anywhere in the string. |
||||||
|
optional bytes contains = 7; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated bytes in = 8; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated bytes not_in = 9; |
||||||
|
|
||||||
|
// WellKnown rules provide advanced constraints against common byte |
||||||
|
// patterns |
||||||
|
oneof well_known { |
||||||
|
// Ip specifies that the field must be a valid IP (v4 or v6) address in |
||||||
|
// byte format |
||||||
|
bool ip = 10; |
||||||
|
|
||||||
|
// Ipv4 specifies that the field must be a valid IPv4 address in byte |
||||||
|
// format |
||||||
|
bool ipv4 = 11; |
||||||
|
|
||||||
|
// Ipv6 specifies that the field must be a valid IPv6 address in byte |
||||||
|
// format |
||||||
|
bool ipv6 = 12; |
||||||
|
} |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 14; |
||||||
|
} |
||||||
|
|
||||||
|
// EnumRules describe the constraints applied to enum values |
||||||
|
message EnumRules { |
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional int32 const = 1; |
||||||
|
|
||||||
|
// DefinedOnly specifies that this field must be only one of the defined |
||||||
|
// values for this enum, failing on any undefined value. |
||||||
|
optional bool defined_only = 2; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated int32 in = 3; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated int32 not_in = 4; |
||||||
|
} |
||||||
|
|
||||||
|
// MessageRules describe the constraints applied to embedded message values. |
||||||
|
// For message-type fields, validation is performed recursively. |
||||||
|
message MessageRules { |
||||||
|
// Skip specifies that the validation rules of this field should not be |
||||||
|
// evaluated |
||||||
|
optional bool skip = 1; |
||||||
|
|
||||||
|
// Required specifies that this field must be set |
||||||
|
optional bool required = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// RepeatedRules describe the constraints applied to `repeated` values |
||||||
|
message RepeatedRules { |
||||||
|
// MinItems specifies that this field must have the specified number of |
||||||
|
// items at a minimum |
||||||
|
optional uint64 min_items = 1; |
||||||
|
|
||||||
|
// MaxItems specifies that this field must have the specified number of |
||||||
|
// items at a maximum |
||||||
|
optional uint64 max_items = 2; |
||||||
|
|
||||||
|
// Unique specifies that all elements in this field must be unique. This |
||||||
|
// contraint is only applicable to scalar and enum types (messages are not |
||||||
|
// supported). |
||||||
|
optional bool unique = 3; |
||||||
|
|
||||||
|
// Items specifies the contraints to be applied to each item in the field. |
||||||
|
// Repeated message fields will still execute validation against each item |
||||||
|
// unless skip is specified here. |
||||||
|
optional FieldRules items = 4; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 5; |
||||||
|
} |
||||||
|
|
||||||
|
// MapRules describe the constraints applied to `map` values |
||||||
|
message MapRules { |
||||||
|
// MinPairs specifies that this field must have the specified number of |
||||||
|
// KVs at a minimum |
||||||
|
optional uint64 min_pairs = 1; |
||||||
|
|
||||||
|
// MaxPairs specifies that this field must have the specified number of |
||||||
|
// KVs at a maximum |
||||||
|
optional uint64 max_pairs = 2; |
||||||
|
|
||||||
|
// NoSparse specifies values in this field cannot be unset. This only |
||||||
|
// applies to map's with message value types. |
||||||
|
optional bool no_sparse = 3; |
||||||
|
|
||||||
|
// Keys specifies the constraints to be applied to each key in the field. |
||||||
|
optional FieldRules keys = 4; |
||||||
|
|
||||||
|
// Values specifies the constraints to be applied to the value of each key |
||||||
|
// in the field. Message values will still have their validations evaluated |
||||||
|
// unless skip is specified here. |
||||||
|
optional FieldRules values = 5; |
||||||
|
|
||||||
|
// IgnoreEmpty specifies that the validation rules of this field should be |
||||||
|
// evaluated only if the field is not empty |
||||||
|
optional bool ignore_empty = 6; |
||||||
|
} |
||||||
|
|
||||||
|
// AnyRules describe constraints applied exclusively to the |
||||||
|
// `google.protobuf.Any` well-known type |
||||||
|
message AnyRules { |
||||||
|
// Required specifies that this field must be set |
||||||
|
optional bool required = 1; |
||||||
|
|
||||||
|
// In specifies that this field's `type_url` must be equal to one of the |
||||||
|
// specified values. |
||||||
|
repeated string in = 2; |
||||||
|
|
||||||
|
// NotIn specifies that this field's `type_url` must not be equal to any of |
||||||
|
// the specified values. |
||||||
|
repeated string not_in = 3; |
||||||
|
} |
||||||
|
|
||||||
|
// DurationRules describe the constraints applied exclusively to the |
||||||
|
// `google.protobuf.Duration` well-known type |
||||||
|
message DurationRules { |
||||||
|
// Required specifies that this field must be set |
||||||
|
optional bool required = 1; |
||||||
|
|
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional google.protobuf.Duration const = 2; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional google.protobuf.Duration lt = 3; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// inclusive |
||||||
|
optional google.protobuf.Duration lte = 4; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive |
||||||
|
optional google.protobuf.Duration gt = 5; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than the specified value, |
||||||
|
// inclusive |
||||||
|
optional google.protobuf.Duration gte = 6; |
||||||
|
|
||||||
|
// In specifies that this field must be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated google.protobuf.Duration in = 7; |
||||||
|
|
||||||
|
// NotIn specifies that this field cannot be equal to one of the specified |
||||||
|
// values |
||||||
|
repeated google.protobuf.Duration not_in = 8; |
||||||
|
} |
||||||
|
|
||||||
|
// TimestampRules describe the constraints applied exclusively to the |
||||||
|
// `google.protobuf.Timestamp` well-known type |
||||||
|
message TimestampRules { |
||||||
|
// Required specifies that this field must be set |
||||||
|
optional bool required = 1; |
||||||
|
|
||||||
|
// Const specifies that this field must be exactly the specified value |
||||||
|
optional google.protobuf.Timestamp const = 2; |
||||||
|
|
||||||
|
// Lt specifies that this field must be less than the specified value, |
||||||
|
// exclusive |
||||||
|
optional google.protobuf.Timestamp lt = 3; |
||||||
|
|
||||||
|
// Lte specifies that this field must be less than the specified value, |
||||||
|
// inclusive |
||||||
|
optional google.protobuf.Timestamp lte = 4; |
||||||
|
|
||||||
|
// Gt specifies that this field must be greater than the specified value, |
||||||
|
// exclusive |
||||||
|
optional google.protobuf.Timestamp gt = 5; |
||||||
|
|
||||||
|
// Gte specifies that this field must be greater than the specified value, |
||||||
|
// inclusive |
||||||
|
optional google.protobuf.Timestamp gte = 6; |
||||||
|
|
||||||
|
// LtNow specifies that this must be less than the current time. LtNow |
||||||
|
// can only be used with the Within rule. |
||||||
|
optional bool lt_now = 7; |
||||||
|
|
||||||
|
// GtNow specifies that this must be greater than the current time. GtNow |
||||||
|
// can only be used with the Within rule. |
||||||
|
optional bool gt_now = 8; |
||||||
|
|
||||||
|
// Within specifies that this field must be within this duration of the |
||||||
|
// current time. This constraint can be used alone or with the LtNow and |
||||||
|
// GtNow rules. |
||||||
|
optional google.protobuf.Duration within = 9; |
||||||
|
} |
Loading…
Reference in new issue