Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
baozhecheng | 3cd4f8126f | 2 years ago |
@ -1,12 +0,0 @@ |
||||
daysUntilStale: 30 |
||||
daysUntilClose: 3 |
||||
exemptLabels: |
||||
- pinned |
||||
- security |
||||
- bug |
||||
staleLabel: wontfix |
||||
markComment: > |
||||
This issue has been automatically marked as stale because it has not had |
||||
recent activity. It will be closed if no further activity occurs. Thank you |
||||
for your contributions. |
||||
closeComment: true |
@ -1,29 +0,0 @@ |
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package project |
||||
|
||||
import ( |
||||
"testing" |
||||
) |
||||
|
||||
func Test_processProjectParams(t *testing.T) { |
||||
type args struct { |
||||
projectName string |
||||
fallbackPlaceDir string |
||||
} |
||||
tests := []struct { |
||||
name string |
||||
args args |
||||
want string |
||||
}{ |
||||
{"absLinux", args{projectName: "/home/kratos/awesome/go/demo", fallbackPlaceDir: ""}, "/home/kratos/awesome/go"}, |
||||
} |
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
if _, got := processProjectParams(tt.args.projectName, tt.args.fallbackPlaceDir); got != tt.want { |
||||
t.Errorf("processProjectParams() = %v, want %v", got, tt.want) |
||||
} |
||||
}) |
||||
} |
||||
} |
@ -1,144 +0,0 @@ |
||||
package project |
||||
|
||||
import ( |
||||
"fmt" |
||||
"go/parser" |
||||
"go/token" |
||||
"os" |
||||
"path/filepath" |
||||
"testing" |
||||
|
||||
"github.com/go-kratos/kratos/cmd/kratos/v2/internal/base" |
||||
) |
||||
|
||||
// TestCmdNew tests the `kratos new` command.
|
||||
func TestCmdNew(t *testing.T) { |
||||
cwd := changeCurrentDir(t) |
||||
projectName := "helloworld" |
||||
|
||||
// create a new project
|
||||
CmdNew.SetArgs([]string{projectName}) |
||||
if err := CmdNew.Execute(); err != nil { |
||||
t.Fatalf("executing command: %v", err) |
||||
} |
||||
|
||||
// check that the expected files were created
|
||||
for _, file := range []string{ |
||||
"go.mod", |
||||
"go.sum", |
||||
"README.md", |
||||
"cmd/helloworld/main.go", |
||||
} { |
||||
if _, err := os.Stat(filepath.Join(cwd, projectName, file)); err != nil { |
||||
t.Errorf("expected file %s to exist", file) |
||||
} |
||||
} |
||||
|
||||
// check that the go.mod file contains the expected module name
|
||||
assertGoMod(t, filepath.Join(cwd, projectName, "go.mod"), projectName) |
||||
|
||||
assertImportsInclude(t, filepath.Join(cwd, projectName, "cmd", projectName, "wire.go"), fmt.Sprintf(`"%s/internal/biz"`, projectName)) |
||||
} |
||||
|
||||
// TestCmdNewNoMod tests the `kratos new` command with the --nomod flag.
|
||||
func TestCmdNewNoMod(t *testing.T) { |
||||
cwd := changeCurrentDir(t) |
||||
|
||||
// create a new project
|
||||
CmdNew.SetArgs([]string{"project"}) |
||||
if err := CmdNew.Execute(); err != nil { |
||||
t.Fatalf("executing command: %v", err) |
||||
} |
||||
|
||||
// add new app with --nomod flag
|
||||
CmdNew.SetArgs([]string{"--nomod", "project/app/user"}) |
||||
if err := CmdNew.Execute(); err != nil { |
||||
t.Fatalf("executing command: %v", err) |
||||
} |
||||
|
||||
// check that the expected files were created
|
||||
for _, file := range []string{ |
||||
"go.mod", |
||||
"go.sum", |
||||
"README.md", |
||||
"cmd/project/main.go", |
||||
"app/user/cmd/user/main.go", |
||||
} { |
||||
if _, err := os.Stat(filepath.Join(cwd, "project", file)); err != nil { |
||||
t.Errorf("expected file %s to exist", file) |
||||
} |
||||
} |
||||
|
||||
assertImportsInclude(t, filepath.Join(cwd, "project/app/user/cmd/user/wire.go"), `"project/app/user/internal/biz"`) |
||||
} |
||||
|
||||
// assertImportsInclude checks that the file at path contains the expected import.
|
||||
func assertImportsInclude(t *testing.T, path, expected string) { |
||||
t.Helper() |
||||
|
||||
got, err := imports(path) |
||||
if err != nil { |
||||
t.Fatalf("getting imports: %v", err) |
||||
} |
||||
|
||||
for _, imp := range got { |
||||
if imp == expected { |
||||
return |
||||
} |
||||
} |
||||
|
||||
t.Errorf("expected imports to include %s, got %v", expected, got) |
||||
} |
||||
|
||||
// imports returns the imports in the file at path.
|
||||
func imports(path string) ([]string, error) { |
||||
fset := token.NewFileSet() |
||||
f, err := parser.ParseFile(fset, path, nil, parser.ImportsOnly) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
imports := make([]string, 0, len(f.Imports)) |
||||
for _, s := range f.Imports { |
||||
imports = append(imports, s.Path.Value) |
||||
} |
||||
|
||||
return imports, nil |
||||
} |
||||
|
||||
// assertGoMod checks that the go.mod file contains the expected module name.
|
||||
func assertGoMod(t *testing.T, path, expected string) { |
||||
t.Helper() |
||||
|
||||
got, err := base.ModulePath(path) |
||||
if err != nil { |
||||
t.Fatalf("getting module path: %v", err) |
||||
} |
||||
|
||||
if got != expected { |
||||
t.Errorf("expected module name %s, got %s", expected, got) |
||||
} |
||||
} |
||||
|
||||
// change the working directory to the tempdir
|
||||
func changeCurrentDir(t *testing.T) string { |
||||
t.Helper() |
||||
|
||||
tmp := t.TempDir() |
||||
|
||||
oldCWD, err := os.Getwd() |
||||
if err != nil { |
||||
t.Fatalf("getting working directory: %v", err) |
||||
} |
||||
|
||||
if err := os.Chdir(tmp); err != nil { |
||||
t.Fatalf("changing working directory: %v", err) |
||||
} |
||||
t.Cleanup(func() { |
||||
if err := os.Chdir(oldCWD); err != nil { |
||||
t.Fatalf("restoring working directory: %v", err) |
||||
} |
||||
}) |
||||
|
||||
return tmp |
||||
} |
@ -1,30 +0,0 @@ |
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package project |
||||
|
||||
import ( |
||||
"testing" |
||||
) |
||||
|
||||
func Test_processProjectParams(t *testing.T) { |
||||
type args struct { |
||||
projectName string |
||||
fallbackPlaceDir string |
||||
} |
||||
tests := []struct { |
||||
name string |
||||
args args |
||||
want string |
||||
}{ |
||||
{"absWindows", args{projectName: "c:\\kratos\\awesome\\go\\demo", fallbackPlaceDir: ""}, "c:\\kratos\\awesome\\go"}, |
||||
//{"relativeWindows", args{projectName: "/home/kratos/awesome/go/demo", fallbackPlaceDir: ""}, "/home/kratos/awesome/go"},
|
||||
} |
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
if _, got := processProjectParams(tt.args.projectName, tt.args.fallbackPlaceDir); got != tt.want { |
||||
t.Errorf("getProjectPlaceDir() = %v, want %v", got, tt.want) |
||||
} |
||||
}) |
||||
} |
||||
} |
@ -1,4 +1,4 @@ |
||||
package main |
||||
|
||||
// release is the current kratos tool version.
|
||||
const release = "v2.6.3" |
||||
const release = "v2.5.2" |
||||
|
@ -0,0 +1,316 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net/http" |
||||
"os" |
||||
"regexp" |
||||
"strings" |
||||
|
||||
"google.golang.org/protobuf/reflect/protoreflect" |
||||
|
||||
"google.golang.org/genproto/googleapis/api/annotations" |
||||
"google.golang.org/protobuf/compiler/protogen" |
||||
"google.golang.org/protobuf/proto" |
||||
"google.golang.org/protobuf/types/descriptorpb" |
||||
) |
||||
|
||||
const ( |
||||
contextPackage = protogen.GoImportPath("context") |
||||
transportHTTPPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http") |
||||
bindingPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http/binding") |
||||
) |
||||
|
||||
var methodSets = make(map[string]int) |
||||
|
||||
// generateFile generates a _http.pb.go file containing kratos errors definitions.
|
||||
func generateFile(gen *protogen.Plugin, file *protogen.File, omitempty bool) *protogen.GeneratedFile { |
||||
if len(file.Services) == 0 || (omitempty && !hasHTTPRule(file.Services)) { |
||||
return nil |
||||
} |
||||
filename := file.GeneratedFilenamePrefix + "_broker.pb.go" |
||||
g := gen.NewGeneratedFile(filename, file.GoImportPath) |
||||
g.P("// Code generated by protoc-gen-go-broker. DO NOT EDIT.") |
||||
g.P("// versions:") |
||||
g.P(fmt.Sprintf("// - protoc-gen-go-broker %s", release)) |
||||
g.P("// - protoc ", protocVersion(gen)) |
||||
if file.Proto.GetOptions().GetDeprecated() { |
||||
g.P("// ", file.Desc.Path(), " is a deprecated file.") |
||||
} else { |
||||
g.P("// source: ", file.Desc.Path()) |
||||
} |
||||
g.P() |
||||
g.P("package ", file.GoPackageName) |
||||
g.P() |
||||
generateFileContent(gen, file, g, omitempty) |
||||
return g |
||||
} |
||||
|
||||
// generateFileContent generates the kratos errors definitions, excluding the package statement.
|
||||
func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, omitempty bool) { |
||||
if len(file.Services) == 0 { |
||||
return |
||||
} |
||||
for _, service := range file.Services { |
||||
genService(gen, file, g, service, omitempty) |
||||
} |
||||
} |
||||
|
||||
func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, service *protogen.Service, omitempty bool) { |
||||
if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() { |
||||
g.P("//") |
||||
g.P(deprecationComment) |
||||
} |
||||
// HTTP Server.
|
||||
sd := &serviceDesc{ |
||||
ServiceType: service.GoName, |
||||
ServiceName: string(service.Desc.FullName()), |
||||
Metadata: file.Desc.Path(), |
||||
} |
||||
for _, method := range service.Methods { |
||||
if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() { |
||||
continue |
||||
} |
||||
rule, ok := proto.GetExtension(method.Desc.Options(), annotations.E_Http).(*annotations.HttpRule) |
||||
if rule != nil && ok { |
||||
for _, bind := range rule.AdditionalBindings { |
||||
sd.Methods = append(sd.Methods, buildHTTPRule(g, method, bind)) |
||||
} |
||||
sd.Methods = append(sd.Methods, buildHTTPRule(g, method, rule)) |
||||
} else if !omitempty { |
||||
path := fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.Desc.Name()) |
||||
sd.Methods = append(sd.Methods, buildMethodDesc(g, method, http.MethodPost, path)) |
||||
} |
||||
} |
||||
if len(sd.Methods) != 0 { |
||||
g.P(sd.execute()) |
||||
} |
||||
} |
||||
|
||||
func hasHTTPRule(services []*protogen.Service) bool { |
||||
for _, service := range services { |
||||
for _, method := range service.Methods { |
||||
if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() { |
||||
continue |
||||
} |
||||
rule, ok := proto.GetExtension(method.Desc.Options(), annotations.E_Http).(*annotations.HttpRule) |
||||
if rule != nil && ok { |
||||
return true |
||||
} |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotations.HttpRule) *methodDesc { |
||||
var ( |
||||
path string |
||||
method string |
||||
body string |
||||
responseBody string |
||||
) |
||||
|
||||
switch pattern := rule.Pattern.(type) { |
||||
case *annotations.HttpRule_Get: |
||||
path = pattern.Get |
||||
method = http.MethodGet |
||||
case *annotations.HttpRule_Put: |
||||
path = pattern.Put |
||||
method = http.MethodPut |
||||
case *annotations.HttpRule_Post: |
||||
path = pattern.Post |
||||
method = http.MethodPost |
||||
case *annotations.HttpRule_Delete: |
||||
path = pattern.Delete |
||||
method = http.MethodDelete |
||||
case *annotations.HttpRule_Patch: |
||||
path = pattern.Patch |
||||
method = http.MethodPatch |
||||
case *annotations.HttpRule_Custom: |
||||
path = pattern.Custom.Path |
||||
method = pattern.Custom.Kind |
||||
} |
||||
body = rule.Body |
||||
responseBody = rule.ResponseBody |
||||
md := buildMethodDesc(g, m, method, path) |
||||
if method == http.MethodGet || method == http.MethodDelete { |
||||
if body != "" { |
||||
_, _ = fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: %s %s body should not be declared.\n", method, path) |
||||
} |
||||
} else { |
||||
if body == "" { |
||||
_, _ = fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: %s %s does not declare a body.\n", method, path) |
||||
} |
||||
} |
||||
if body == "*" { |
||||
md.HasBody = true |
||||
md.Body = "" |
||||
} else if body != "" { |
||||
md.HasBody = true |
||||
md.Body = "." + camelCaseVars(body) |
||||
} else { |
||||
md.HasBody = false |
||||
} |
||||
if responseBody == "*" { |
||||
md.ResponseBody = "" |
||||
} else if responseBody != "" { |
||||
md.ResponseBody = "." + camelCaseVars(responseBody) |
||||
} |
||||
return md |
||||
} |
||||
|
||||
func buildMethodDesc(g *protogen.GeneratedFile, m *protogen.Method, method, path string) *methodDesc { |
||||
defer func() { methodSets[m.GoName]++ }() |
||||
|
||||
vars := buildPathVars(path) |
||||
|
||||
for v, s := range vars { |
||||
fields := m.Input.Desc.Fields() |
||||
|
||||
if s != nil { |
||||
path = replacePath(v, *s, path) |
||||
} |
||||
for _, field := range strings.Split(v, ".") { |
||||
if strings.TrimSpace(field) == "" { |
||||
continue |
||||
} |
||||
if strings.Contains(field, ":") { |
||||
field = strings.Split(field, ":")[0] |
||||
} |
||||
fd := fields.ByName(protoreflect.Name(field)) |
||||
if fd == nil { |
||||
fmt.Fprintf(os.Stderr, "\u001B[31mERROR\u001B[m: The corresponding field '%s' declaration in message could not be found in '%s'\n", v, path) |
||||
os.Exit(2) |
||||
} |
||||
if fd.IsMap() { |
||||
fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: The field in path:'%s' shouldn't be a map.\n", v) |
||||
} else if fd.IsList() { |
||||
fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: The field in path:'%s' shouldn't be a list.\n", v) |
||||
} else if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind { |
||||
fields = fd.Message().Fields() |
||||
} |
||||
} |
||||
} |
||||
return &methodDesc{ |
||||
Name: m.GoName, |
||||
OriginalName: string(m.Desc.Name()), |
||||
Num: methodSets[m.GoName], |
||||
Request: g.QualifiedGoIdent(m.Input.GoIdent), |
||||
Reply: g.QualifiedGoIdent(m.Output.GoIdent), |
||||
Path: path, |
||||
Method: method, |
||||
HasVars: len(vars) > 0, |
||||
} |
||||
} |
||||
|
||||
func buildPathVars(path string) (res map[string]*string) { |
||||
if strings.HasSuffix(path, "/") { |
||||
fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: Path %s should not end with \"/\" \n", path) |
||||
} |
||||
pattern := regexp.MustCompile(`(?i){([a-z.0-9_\s]*)=?([^{}]*)}`) |
||||
matches := pattern.FindAllStringSubmatch(path, -1) |
||||
res = make(map[string]*string, len(matches)) |
||||
for _, m := range matches { |
||||
name := strings.TrimSpace(m[1]) |
||||
if len(name) > 1 && len(m[2]) > 0 { |
||||
res[name] = &m[2] |
||||
} else { |
||||
res[name] = nil |
||||
} |
||||
} |
||||
return |
||||
} |
||||
|
||||
func replacePath(name string, value string, path string) string { |
||||
pattern := regexp.MustCompile(fmt.Sprintf(`(?i){([\s]*%s[\s]*)=?([^{}]*)}`, name)) |
||||
idx := pattern.FindStringIndex(path) |
||||
if len(idx) > 0 { |
||||
path = fmt.Sprintf("%s{%s:%s}%s", |
||||
path[:idx[0]], // The start of the match
|
||||
name, |
||||
strings.ReplaceAll(value, "*", ".*"), |
||||
path[idx[1]:], |
||||
) |
||||
} |
||||
return path |
||||
} |
||||
|
||||
func camelCaseVars(s string) string { |
||||
subs := strings.Split(s, ".") |
||||
vars := make([]string, 0, len(subs)) |
||||
for _, sub := range subs { |
||||
vars = append(vars, camelCase(sub)) |
||||
} |
||||
return strings.Join(vars, ".") |
||||
} |
||||
|
||||
// camelCase returns the CamelCased name.
|
||||
// If there is an interior underscore followed by a lower case letter,
|
||||
// drop the underscore and convert the letter to upper case.
|
||||
// There is a remote possibility of this rewrite causing a name collision,
|
||||
// but it's so remote we're prepared to pretend it's nonexistent - since the
|
||||
// C++ generator lowercase names, it's extremely unlikely to have two fields
|
||||
// with different capitalization.
|
||||
// In short, _my_field_name_2 becomes XMyFieldName_2.
|
||||
func camelCase(s string) string { |
||||
if s == "" { |
||||
return "" |
||||
} |
||||
t := make([]byte, 0, 32) |
||||
i := 0 |
||||
if s[0] == '_' { |
||||
// Need a capital letter; drop the '_'.
|
||||
t = append(t, 'X') |
||||
i++ |
||||
} |
||||
// Invariant: if the next letter is lower case, it must be converted
|
||||
// to upper case.
|
||||
// That is, we process a word at a time, where words are marked by _ or
|
||||
// upper case letter. Digits are treated as words.
|
||||
for ; i < len(s); i++ { |
||||
c := s[i] |
||||
if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) { |
||||
continue // Skip the underscore in s.
|
||||
} |
||||
if isASCIIDigit(c) { |
||||
t = append(t, c) |
||||
continue |
||||
} |
||||
// Assume we have a letter now - if not, it's a bogus identifier.
|
||||
// The next word is a sequence of characters that must start upper case.
|
||||
if isASCIILower(c) { |
||||
c ^= ' ' // Make it a capital letter.
|
||||
} |
||||
t = append(t, c) // Guaranteed not lower case.
|
||||
// Accept lower case sequence that follows.
|
||||
for i+1 < len(s) && isASCIILower(s[i+1]) { |
||||
i++ |
||||
t = append(t, s[i]) |
||||
} |
||||
} |
||||
return string(t) |
||||
} |
||||
|
||||
// Is c an ASCII lower-case letter?
|
||||
func isASCIILower(c byte) bool { |
||||
return 'a' <= c && c <= 'z' |
||||
} |
||||
|
||||
// Is c an ASCII digit?
|
||||
func isASCIIDigit(c byte) bool { |
||||
return '0' <= c && c <= '9' |
||||
} |
||||
|
||||
func protocVersion(gen *protogen.Plugin) string { |
||||
v := gen.Request.GetCompilerVersion() |
||||
if v == nil { |
||||
return "(unknown)" |
||||
} |
||||
var suffix string |
||||
if s := v.GetSuffix(); s != "" { |
||||
suffix = "-" + s |
||||
} |
||||
return fmt.Sprintf("v%d.%d.%d%s", v.GetMajor(), v.GetMinor(), v.GetPatch(), suffix) |
||||
} |
||||
|
||||
const deprecationComment = "// Deprecated: Do not use." |
@ -0,0 +1,113 @@ |
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.19.4
|
||||
// source: cmd/proto-gen-go-broker/broker/broker.proto
|
||||
|
||||
package broker |
||||
|
||||
import ( |
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect" |
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl" |
||||
descriptorpb "google.golang.org/protobuf/types/descriptorpb" |
||||
reflect "reflect" |
||||
) |
||||
|
||||
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) |
||||
) |
||||
|
||||
var file_cmd_proto_gen_go_broker_broker_broker_proto_extTypes = []protoimpl.ExtensionInfo{ |
||||
{ |
||||
ExtendedType: (*descriptorpb.MethodOptions)(nil), |
||||
ExtensionType: (*string)(nil), |
||||
Field: 1001011, |
||||
Name: "errors.receive_topic", |
||||
Tag: "bytes,1001011,opt,name=receive_topic", |
||||
Filename: "cmd/proto-gen-go-broker/broker/broker.proto", |
||||
}, |
||||
{ |
||||
ExtendedType: (*descriptorpb.MethodOptions)(nil), |
||||
ExtensionType: (*string)(nil), |
||||
Field: 1008611, |
||||
Name: "errors.output_topic", |
||||
Tag: "bytes,1008611,opt,name=output_topic", |
||||
Filename: "cmd/proto-gen-go-broker/broker/broker.proto", |
||||
}, |
||||
} |
||||
|
||||
// Extension fields to descriptorpb.MethodOptions.
|
||||
var ( |
||||
// optional string receive_topic = 1001011;
|
||||
E_ReceiveTopic = &file_cmd_proto_gen_go_broker_broker_broker_proto_extTypes[0] |
||||
// optional string output_topic = 1008611;
|
||||
E_OutputTopic = &file_cmd_proto_gen_go_broker_broker_broker_proto_extTypes[1] |
||||
) |
||||
|
||||
var File_cmd_proto_gen_go_broker_broker_broker_proto protoreflect.FileDescriptor |
||||
|
||||
var file_cmd_proto_gen_go_broker_broker_broker_proto_rawDesc = []byte{ |
||||
0x0a, 0x2b, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x67, 0x65, 0x6e, 0x2d, |
||||
0x67, 0x6f, 0x2d, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, |
||||
0x2f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x65, |
||||
0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, |
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, |
||||
0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x45, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x65, 0x69, |
||||
0x76, 0x65, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, |
||||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, |
||||
0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb3, 0x8c, 0x3d, 0x20, 0x01, 0x28, 0x09, |
||||
0x52, 0x0c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x3a, 0x43, |
||||
0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x1e, |
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, |
||||
0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe3, |
||||
0xc7, 0x3d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x6f, |
||||
0x70, 0x69, 0x63, 0x42, 0x6a, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, |
||||
0x62, 0x2e, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x50, |
||||
0x01, 0x5a, 0x3d, 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, 0x76, |
||||
0x32, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x67, 0x65, 0x6e, 0x2d, |
||||
0x67, 0x6f, 0x2d, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x3b, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, |
||||
0xa2, 0x02, 0x0c, 0x4b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x62, |
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, |
||||
} |
||||
|
||||
var file_cmd_proto_gen_go_broker_broker_broker_proto_goTypes = []interface{}{ |
||||
(*descriptorpb.MethodOptions)(nil), // 0: google.protobuf.MethodOptions
|
||||
} |
||||
var file_cmd_proto_gen_go_broker_broker_broker_proto_depIdxs = []int32{ |
||||
0, // 0: errors.receive_topic:extendee -> google.protobuf.MethodOptions
|
||||
0, // 1: errors.output_topic:extendee -> google.protobuf.MethodOptions
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
0, // [0:2] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
} |
||||
|
||||
func init() { file_cmd_proto_gen_go_broker_broker_broker_proto_init() } |
||||
func file_cmd_proto_gen_go_broker_broker_broker_proto_init() { |
||||
if File_cmd_proto_gen_go_broker_broker_broker_proto != nil { |
||||
return |
||||
} |
||||
type x struct{} |
||||
out := protoimpl.TypeBuilder{ |
||||
File: protoimpl.DescBuilder{ |
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), |
||||
RawDescriptor: file_cmd_proto_gen_go_broker_broker_broker_proto_rawDesc, |
||||
NumEnums: 0, |
||||
NumMessages: 0, |
||||
NumExtensions: 2, |
||||
NumServices: 0, |
||||
}, |
||||
GoTypes: file_cmd_proto_gen_go_broker_broker_broker_proto_goTypes, |
||||
DependencyIndexes: file_cmd_proto_gen_go_broker_broker_broker_proto_depIdxs, |
||||
ExtensionInfos: file_cmd_proto_gen_go_broker_broker_broker_proto_extTypes, |
||||
}.Build() |
||||
File_cmd_proto_gen_go_broker_broker_broker_proto = out.File |
||||
file_cmd_proto_gen_go_broker_broker_broker_proto_rawDesc = nil |
||||
file_cmd_proto_gen_go_broker_broker_broker_proto_goTypes = nil |
||||
file_cmd_proto_gen_go_broker_broker_broker_proto_depIdxs = nil |
||||
} |
@ -0,0 +1,17 @@ |
||||
syntax = "proto3"; |
||||
|
||||
package errors; |
||||
|
||||
option go_package = "github.com/go-kratos/kratos/v2/cmd/proto-gen-go-broker;broker"; |
||||
option java_multiple_files = true; |
||||
option java_package = "com.github.kratos.Broker"; |
||||
option objc_class_prefix = "KratosBroker"; |
||||
|
||||
import "google/protobuf/descriptor.proto"; |
||||
|
||||
|
||||
|
||||
extend google.protobuf.MethodOptions { |
||||
string receive_topic = 1001011; |
||||
string output_topic = 1008611; |
||||
} |
@ -0,0 +1,87 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"reflect" |
||||
"testing" |
||||
) |
||||
|
||||
func TestNoParameters(t *testing.T) { |
||||
path := "/test/noparams" |
||||
m := buildPathVars(path) |
||||
if !reflect.DeepEqual(m, map[string]*string{}) { |
||||
t.Fatalf("Map should be empty") |
||||
} |
||||
} |
||||
|
||||
func TestSingleParam(t *testing.T) { |
||||
path := "/test/{message.id}" |
||||
m := buildPathVars(path) |
||||
if !reflect.DeepEqual(len(m), 1) { |
||||
t.Fatalf("len(m) not is 1") |
||||
} |
||||
if m["message.id"] != nil { |
||||
t.Fatalf(`m["message.id"] should be empty`) |
||||
} |
||||
} |
||||
|
||||
func TestTwoParametersReplacement(t *testing.T) { |
||||
path := "/test/{message.id}/{message.name=messages/*}" |
||||
m := buildPathVars(path) |
||||
if len(m) != 2 { |
||||
t.Fatal("len(m) should be 2") |
||||
} |
||||
if m["message.id"] != nil { |
||||
t.Fatal(`m["message.id"] should be nil`) |
||||
} |
||||
if m["message.name"] == nil { |
||||
t.Fatal(`m["message.name"] should not be nil`) |
||||
} |
||||
if *m["message.name"] != "messages/*" { |
||||
t.Fatal(`m["message.name"] should be "messages/*"`) |
||||
} |
||||
} |
||||
|
||||
func TestNoReplacePath(t *testing.T) { |
||||
path := "/test/{message.id=test}" |
||||
if !reflect.DeepEqual(replacePath("message.id", "test", path), "/test/{message.id:test}") { |
||||
t.Fatal(`replacePath("message.id", "test", path) should be "/test/{message.id:test}"`) |
||||
} |
||||
path = "/test/{message.id=test/*}" |
||||
if !reflect.DeepEqual(replacePath("message.id", "test/*", path), "/test/{message.id:test/.*}") { |
||||
t.Fatal(`replacePath("message.id", "test/*", path) should be "/test/{message.id:test/.*}"`) |
||||
} |
||||
} |
||||
|
||||
func TestReplacePath(t *testing.T) { |
||||
path := "/test/{message.id}/{message.name=messages/*}" |
||||
newPath := replacePath("message.name", "messages/*", path) |
||||
if !reflect.DeepEqual("/test/{message.id}/{message.name:messages/.*}", newPath) { |
||||
t.Fatal(`replacePath("message.name", "messages/*", path) should be "/test/{message.id}/{message.name:messages/.*}"`) |
||||
} |
||||
} |
||||
|
||||
func TestIteration(t *testing.T) { |
||||
path := "/test/{message.id}/{message.name=messages/*}" |
||||
vars := buildPathVars(path) |
||||
for v, s := range vars { |
||||
if s != nil { |
||||
path = replacePath(v, *s, path) |
||||
} |
||||
} |
||||
if !reflect.DeepEqual("/test/{message.id}/{message.name:messages/.*}", path) { |
||||
t.Fatal(`replacePath("message.name", "messages/*", path) should be "/test/{message.id}/{message.name:messages/.*}"`) |
||||
} |
||||
} |
||||
|
||||
func TestIterationMiddle(t *testing.T) { |
||||
path := "/test/{message.name=messages/*}/books" |
||||
vars := buildPathVars(path) |
||||
for v, s := range vars { |
||||
if s != nil { |
||||
path = replacePath(v, *s, path) |
||||
} |
||||
} |
||||
if !reflect.DeepEqual("/test/{message.name:messages/.*}/books", path) { |
||||
t.Fatal(`replacePath("message.name", "messages/*", path) should be "/test/{message.name:messages/.*}/books"`) |
||||
} |
||||
} |
@ -0,0 +1,8 @@ |
||||
module github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2 |
||||
|
||||
go 1.16 |
||||
|
||||
require ( |
||||
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd |
||||
google.golang.org/protobuf v1.28.0 |
||||
) |
@ -0,0 +1,34 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"flag" |
||||
"fmt" |
||||
|
||||
"google.golang.org/protobuf/compiler/protogen" |
||||
"google.golang.org/protobuf/types/pluginpb" |
||||
) |
||||
|
||||
var ( |
||||
showVersion = flag.Bool("version", false, "print the version and exit") |
||||
omitempty = flag.Bool("omitempty", true, "omit if google.api is empty") |
||||
) |
||||
|
||||
func main() { |
||||
flag.Parse() |
||||
if *showVersion { |
||||
fmt.Printf("protoc-gen-go-http %v\n", release) |
||||
return |
||||
} |
||||
protogen.Options{ |
||||
ParamFunc: flag.CommandLine.Set, |
||||
}.Run(func(gen *protogen.Plugin) error { |
||||
gen.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) |
||||
for _, f := range gen.Files { |
||||
if !f.Generate { |
||||
continue |
||||
} |
||||
generateFile(gen, f, *omitempty) |
||||
} |
||||
return nil |
||||
}) |
||||
} |
@ -0,0 +1,4 @@ |
||||
package main |
||||
|
||||
// release is the current protoc-gen-go-http version.
|
||||
const release = "v2.5.2" |
@ -1,17 +0,0 @@ |
||||
{{ range .Errors }} |
||||
|
||||
{{ if .HasComment }}{{ .Comment }}{{ end -}} |
||||
func Is{{.CamelValue}}(err error) bool { |
||||
if err == nil { |
||||
return false |
||||
} |
||||
e := errors.FromError(err) |
||||
return e.Reason == {{ .Name }}_{{ .Value }}.String() && e.Code == {{ .HTTPCode }} |
||||
} |
||||
|
||||
{{ if .HasComment }}{{ .Comment }}{{ end -}} |
||||
func Error{{ .CamelValue }}(format string, args ...interface{}) *errors.Error { |
||||
return errors.New({{ .HTTPCode }}, {{ .Name }}_{{ .Value }}.String(), fmt.Sprintf(format, args...)) |
||||
} |
||||
|
||||
{{- end }} |
@ -1,4 +1,4 @@ |
||||
package main |
||||
|
||||
// release is the current protoc-gen-go-errors version.
|
||||
const release = "v2.6.3" |
||||
const release = "v2.5.2" |
||||
|
@ -1,4 +1,4 @@ |
||||
package main |
||||
|
||||
// release is the current protoc-gen-go-http version.
|
||||
const release = "v2.6.3" |
||||
const release = "v2.5.2" |
||||
|
@ -1,90 +0,0 @@ |
||||
package apollo |
||||
|
||||
import ( |
||||
"testing" |
||||
) |
||||
|
||||
func Test_genKey(t *testing.T) { |
||||
type args struct { |
||||
ns string |
||||
sub string |
||||
} |
||||
tests := []struct { |
||||
name string |
||||
args args |
||||
want string |
||||
}{ |
||||
{ |
||||
name: "blank namespace", |
||||
args: args{ |
||||
ns: "", |
||||
sub: "x.y", |
||||
}, |
||||
want: "x.y", |
||||
}, |
||||
{ |
||||
name: "properties namespace", |
||||
args: args{ |
||||
ns: "application", |
||||
sub: "x.y", |
||||
}, |
||||
want: "application.x.y", |
||||
}, |
||||
{ |
||||
name: "namespace with format", |
||||
args: args{ |
||||
ns: "app.yaml", |
||||
sub: "x.y", |
||||
}, |
||||
want: "app.x.y", |
||||
}, |
||||
} |
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
if got := genKey(tt.args.ns, tt.args.sub); got != tt.want { |
||||
t.Errorf("genKey() = %v, want %v", got, tt.want) |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
|
||||
func Test_format(t *testing.T) { |
||||
tests := []struct { |
||||
name string |
||||
namespace string |
||||
want string |
||||
}{ |
||||
{ |
||||
name: "properties namespace", |
||||
namespace: "application", |
||||
want: "json", |
||||
}, |
||||
{ |
||||
name: "properties namespace #1", |
||||
namespace: "app.setting", |
||||
want: "json", |
||||
}, |
||||
{ |
||||
name: "namespace with format[yaml]", |
||||
namespace: "app.yaml", |
||||
want: "yaml", |
||||
}, |
||||
{ |
||||
name: "namespace with format[yml]", |
||||
namespace: "app.yml", |
||||
want: "yml", |
||||
}, |
||||
{ |
||||
name: "namespace with format[json]", |
||||
namespace: "app.json", |
||||
want: "json", |
||||
}, |
||||
} |
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
if got := format(tt.namespace); got != tt.want { |
||||
t.Errorf("format() = %v, want %v", got, tt.want) |
||||
} |
||||
}) |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue