forked from cloudwego/hertz
Merge pull request #311 from FGYFFFF/feat/handler_by_method
feat(hz): generate a separate handler file for each method
This commit is contained in:
commit
d6b85fec12
|
@ -123,6 +123,7 @@ func Init() *cli.App {
|
||||||
snakeNameFlag := cli.BoolFlag{Name: "snake_tag", Usage: "Use snake_case style naming for tags. (Only works for 'form', 'query', 'json')", Destination: &globalArgs.SnakeName}
|
snakeNameFlag := cli.BoolFlag{Name: "snake_tag", Usage: "Use snake_case style naming for tags. (Only works for 'form', 'query', 'json')", Destination: &globalArgs.SnakeName}
|
||||||
customLayout := cli.StringFlag{Name: "customize_layout", Usage: "Specify the layout template. ({{Template Profile}}:{{Rendering Data}})", Destination: &globalArgs.CustomizeLayout}
|
customLayout := cli.StringFlag{Name: "customize_layout", Usage: "Specify the layout template. ({{Template Profile}}:{{Rendering Data}})", Destination: &globalArgs.CustomizeLayout}
|
||||||
customPackage := cli.StringFlag{Name: "customize_package", Usage: "Specify the package template. ({{Template Profile}}:)", Destination: &globalArgs.CustomizePackage}
|
customPackage := cli.StringFlag{Name: "customize_package", Usage: "Specify the package template. ({{Template Profile}}:)", Destination: &globalArgs.CustomizePackage}
|
||||||
|
handlerByMethod := cli.BoolFlag{Name: "handler_by_method", Usage: "Generate a separate handler file for each method.", Destination: &globalArgs.HandlerByMethod}
|
||||||
|
|
||||||
// app
|
// app
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
|
@ -164,6 +165,7 @@ func Init() *cli.App {
|
||||||
&excludeFilesFlag,
|
&excludeFilesFlag,
|
||||||
&customLayout,
|
&customLayout,
|
||||||
&customPackage,
|
&customPackage,
|
||||||
|
&handlerByMethod,
|
||||||
&protoPluginsFlag,
|
&protoPluginsFlag,
|
||||||
&thriftPluginsFlag,
|
&thriftPluginsFlag,
|
||||||
},
|
},
|
||||||
|
@ -191,6 +193,7 @@ func Init() *cli.App {
|
||||||
&snakeNameFlag,
|
&snakeNameFlag,
|
||||||
&excludeFilesFlag,
|
&excludeFilesFlag,
|
||||||
&customPackage,
|
&customPackage,
|
||||||
|
&handlerByMethod,
|
||||||
&protoPluginsFlag,
|
&protoPluginsFlag,
|
||||||
&thriftPluginsFlag,
|
&thriftPluginsFlag,
|
||||||
},
|
},
|
||||||
|
|
|
@ -61,6 +61,7 @@ type Argument struct {
|
||||||
SnakeName bool
|
SnakeName bool
|
||||||
Excludes []string
|
Excludes []string
|
||||||
NoRecurse bool
|
NoRecurse bool
|
||||||
|
HandlerByMethod bool
|
||||||
|
|
||||||
CustomizeLayout string
|
CustomizeLayout string
|
||||||
CustomizePackage string
|
CustomizePackage string
|
||||||
|
|
|
@ -36,6 +36,7 @@ type HttpMethod struct {
|
||||||
ReturnTypeName string
|
ReturnTypeName string
|
||||||
Path string
|
Path string
|
||||||
Serializer string
|
Serializer string
|
||||||
|
OutputDir string
|
||||||
// Annotations map[string]string
|
// Annotations map[string]string
|
||||||
Models map[string]*model.Model
|
Models map[string]*model.Model
|
||||||
}
|
}
|
||||||
|
@ -54,29 +55,37 @@ type Client struct {
|
||||||
|
|
||||||
func (pkgGen *HttpPackageGenerator) genHandler(pkg *HttpPackage, handlerDir, handlerPackage string, root *RouterNode) error {
|
func (pkgGen *HttpPackageGenerator) genHandler(pkg *HttpPackage, handlerDir, handlerPackage string, root *RouterNode) error {
|
||||||
for _, s := range pkg.Services {
|
for _, s := range pkg.Services {
|
||||||
handler := Handler{
|
var handler Handler
|
||||||
FilePath: filepath.Join(handlerDir, util.ToSnakeCase(s.Name)+".go"),
|
if pkgGen.HandlerByMethod { // generate handler by method
|
||||||
PackageName: util.SplitPackage(handlerPackage, ""),
|
for _, m := range s.Methods {
|
||||||
Methods: s.Methods,
|
handler = Handler{
|
||||||
}
|
FilePath: filepath.Join(handlerDir, m.OutputDir, util.ToSnakeCase(m.Name)+".go"),
|
||||||
|
PackageName: util.SplitPackage(handlerPackage, ""),
|
||||||
handler.Imports = make(map[string]*model.Model, len(s.Methods))
|
Methods: []*HttpMethod{m},
|
||||||
for _, m := range s.Methods {
|
}
|
||||||
for key, mm := range m.Models {
|
|
||||||
if v, ok := handler.Imports[mm.PackageName]; ok && v.Package != mm.Package {
|
if err := pkgGen.processHandler(&handler, root, handlerDir, m.OutputDir, true); err != nil {
|
||||||
handler.Imports[key] = mm
|
return fmt.Errorf("generate handler %s failed, err: %v", handler.FilePath, err.Error())
|
||||||
continue
|
}
|
||||||
|
|
||||||
|
if err := pkgGen.updateHandler(handler, handlerTplName, handler.FilePath, false); err != nil {
|
||||||
|
return fmt.Errorf("generate handler %s failed, err: %v", handler.FilePath, err.Error())
|
||||||
}
|
}
|
||||||
handler.Imports[mm.PackageName] = mm
|
|
||||||
}
|
}
|
||||||
err := root.Update(m, handler.PackageName)
|
} else { // generate handler service
|
||||||
if err != nil {
|
handler = Handler{
|
||||||
return err
|
FilePath: filepath.Join(handlerDir, util.ToSnakeCase(s.Name)+".go"),
|
||||||
|
PackageName: util.SplitPackage(handlerPackage, ""),
|
||||||
|
Methods: s.Methods,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := pkgGen.processHandler(&handler, root, "", "", false); err != nil {
|
||||||
|
return fmt.Errorf("generate handler %s failed, err: %v", handler.FilePath, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := pkgGen.updateHandler(handler, handlerTplName, handler.FilePath, false); err != nil {
|
||||||
|
return fmt.Errorf("generate handler %s failed, err: %v", handler.FilePath, err.Error())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
handler.Format()
|
|
||||||
if err := pkgGen.updateHandler(handler, handlerTplName, handler.FilePath, false); err != nil {
|
|
||||||
return fmt.Errorf("generate handler %s failed, err: %v", handler.FilePath, err.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pkgGen.ClientDir) != 0 {
|
if len(pkgGen.ClientDir) != 0 {
|
||||||
|
@ -96,6 +105,31 @@ func (pkgGen *HttpPackageGenerator) genHandler(pkg *HttpPackage, handlerDir, han
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pkgGen *HttpPackageGenerator) processHandler(handler *Handler, root *RouterNode, handlerDir, projectOutDir string, handlerByMethod bool) error {
|
||||||
|
singleHandlerPackage := ""
|
||||||
|
if handlerByMethod {
|
||||||
|
singleHandlerPackage = util.SubPackage(pkgGen.ProjPackage, filepath.Join(handlerDir, projectOutDir))
|
||||||
|
}
|
||||||
|
handler.Imports = make(map[string]*model.Model, len(handler.Methods))
|
||||||
|
for _, m := range handler.Methods {
|
||||||
|
// Iterate over the request and return parameters of the method to get import path.
|
||||||
|
for key, mm := range m.Models {
|
||||||
|
if v, ok := handler.Imports[mm.PackageName]; ok && v.Package != mm.Package {
|
||||||
|
handler.Imports[key] = mm
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
handler.Imports[mm.PackageName] = mm
|
||||||
|
}
|
||||||
|
err := root.Update(m, handler.PackageName, singleHandlerPackage)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.Format()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (pkgGen *HttpPackageGenerator) updateHandler(handler interface{}, handlerTpl, filePath string, noRepeat bool) error {
|
func (pkgGen *HttpPackageGenerator) updateHandler(handler interface{}, handlerTpl, filePath string, noRepeat bool) error {
|
||||||
isExist, err := util.PathExist(filePath)
|
isExist, err := util.PathExist(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -44,15 +44,16 @@ type Service struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type HttpPackageGenerator struct {
|
type HttpPackageGenerator struct {
|
||||||
ConfigPath string
|
ConfigPath string
|
||||||
Backend meta.Backend
|
Backend meta.Backend
|
||||||
Options []Option
|
Options []Option
|
||||||
ProjPackage string
|
ProjPackage string
|
||||||
HandlerDir string
|
HandlerDir string
|
||||||
RouterDir string
|
RouterDir string
|
||||||
ModelDir string
|
ModelDir string
|
||||||
ClientDir string
|
ClientDir string
|
||||||
NeedModel bool
|
NeedModel bool
|
||||||
|
HandlerByMethod bool
|
||||||
|
|
||||||
loadedBackend Backend
|
loadedBackend Backend
|
||||||
curModel *model.Model
|
curModel *model.Model
|
||||||
|
@ -135,7 +136,11 @@ func (pkgGen *HttpPackageGenerator) Generate(pkg *HttpPackage) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is for handler_by_service, the handler_dir is {$HANDLER_DIR}/{$PKG}
|
||||||
handlerDir := util.SubDir(pkgGen.HandlerDir, pkg.Package)
|
handlerDir := util.SubDir(pkgGen.HandlerDir, pkg.Package)
|
||||||
|
if pkgGen.HandlerByMethod {
|
||||||
|
handlerDir = pkgGen.HandlerDir
|
||||||
|
}
|
||||||
handlerPackage := util.SubPackage(pkgGen.ProjPackage, handlerDir)
|
handlerPackage := util.SubPackage(pkgGen.ProjPackage, handlerDir)
|
||||||
routerDir := util.SubDir(pkgGen.RouterDir, pkg.Package)
|
routerDir := util.SubDir(pkgGen.RouterDir, pkg.Package)
|
||||||
routerPackage := util.SubPackage(pkgGen.ProjPackage, routerDir)
|
routerPackage := util.SubPackage(pkgGen.ProjPackage, routerDir)
|
||||||
|
|
|
@ -97,7 +97,9 @@ package {{$.PackageName}}
|
||||||
import (
|
import (
|
||||||
"github.com/cloudwego/hertz/pkg/app/server"
|
"github.com/cloudwego/hertz/pkg/app/server"
|
||||||
|
|
||||||
{{range $k, $v := .HandlerPackages}}{{$k}} "{{$v}}"{{end}}
|
{{- range $k, $v := .HandlerPackages}}
|
||||||
|
{{$k}} "{{$v}}"
|
||||||
|
{{- end}}
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -42,8 +42,10 @@ type RouterNode struct {
|
||||||
Path string
|
Path string
|
||||||
Children childrenRouterInfo
|
Children childrenRouterInfo
|
||||||
|
|
||||||
Handler string // {{HandlerPackage}}.{{HandlerName}}
|
Handler string // {{HandlerPackage}}.{{HandlerName}}
|
||||||
HttpMethod string
|
HandlerPackage string
|
||||||
|
HandlerPackageAlias string
|
||||||
|
HttpMethod string
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegisterDependency struct {
|
type RegisterDependency struct {
|
||||||
|
@ -64,7 +66,7 @@ func (routerNode *RouterNode) Sort() {
|
||||||
sort.Sort(routerNode.Children)
|
sort.Sort(routerNode.Children)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (routerNode *RouterNode) Update(method *HttpMethod, handlerType string) error {
|
func (routerNode *RouterNode) Update(method *HttpMethod, handlerType, handlerPkg string) error {
|
||||||
if method.Path == "" {
|
if method.Path == "" {
|
||||||
return fmt.Errorf("empty path for method '%s'", method.Name)
|
return fmt.Errorf("empty path for method '%s'", method.Name)
|
||||||
}
|
}
|
||||||
|
@ -77,7 +79,7 @@ func (routerNode *RouterNode) Update(method *HttpMethod, handlerType string) err
|
||||||
return fmt.Errorf("path '%s' has been registered", method.Path)
|
return fmt.Errorf("path '%s' has been registered", method.Path)
|
||||||
}
|
}
|
||||||
name := util.ToVarName(paths[:last])
|
name := util.ToVarName(paths[:last])
|
||||||
parent.Insert(name, method, handlerType, paths[last:])
|
parent.Insert(name, method, handlerType, paths[last:], handlerPkg)
|
||||||
parent.Sort()
|
parent.Sort()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -136,14 +138,36 @@ func (routerNode *RouterNode) DFS(i int, hook func(layer int, node *RouterNode)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (routerNode *RouterNode) Insert(name string, method *HttpMethod, handlerType string, paths []string) {
|
var handlerPkgMap map[string]string
|
||||||
|
|
||||||
|
func (routerNode *RouterNode) Insert(name string, method *HttpMethod, handlerType string, paths []string, handlerPkg string) {
|
||||||
cur := routerNode
|
cur := routerNode
|
||||||
for i, p := range paths {
|
for i, p := range paths {
|
||||||
c := &RouterNode{
|
c := &RouterNode{
|
||||||
Path: "/" + p,
|
Path: "/" + p,
|
||||||
}
|
}
|
||||||
if i == len(paths)-1 {
|
if i == len(paths)-1 {
|
||||||
c.Handler = handlerType + "." + method.Name
|
// generate handler by method
|
||||||
|
if len(handlerPkg) != 0 {
|
||||||
|
// get a unique package alias for every handler
|
||||||
|
pkgAlias := filepath.Base(handlerPkg)
|
||||||
|
pkgAlias = util.ToVarName([]string{pkgAlias})
|
||||||
|
val, exist := handlerPkgMap[handlerPkg]
|
||||||
|
if !exist {
|
||||||
|
pkgAlias, _ = util.GetHandlerPackageUniqueName(pkgAlias)
|
||||||
|
if len(handlerPkgMap) == 0 {
|
||||||
|
handlerPkgMap = make(map[string]string, 10)
|
||||||
|
}
|
||||||
|
handlerPkgMap[handlerPkg] = pkgAlias
|
||||||
|
} else {
|
||||||
|
pkgAlias = val
|
||||||
|
}
|
||||||
|
c.HandlerPackageAlias = pkgAlias
|
||||||
|
c.Handler = pkgAlias + "." + method.Name
|
||||||
|
c.HandlerPackage = handlerPkg
|
||||||
|
} else { // generate handler by service
|
||||||
|
c.Handler = handlerType + "." + method.Name
|
||||||
|
}
|
||||||
c.HttpMethod = getHttpMethod(method.HTTPMethod)
|
c.HttpMethod = getHttpMethod(method.HTTPMethod)
|
||||||
}
|
}
|
||||||
if cur.Children == nil {
|
if cur.Children == nil {
|
||||||
|
@ -272,6 +296,19 @@ func (pkgGen *HttpPackageGenerator) genRouter(pkg *HttpPackage, root *RouterNode
|
||||||
},
|
},
|
||||||
Router: root,
|
Router: root,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pkgGen.HandlerByMethod {
|
||||||
|
handlerMap := make(map[string]string, 1)
|
||||||
|
hook := func(layer int, node *RouterNode) error {
|
||||||
|
if len(node.HandlerPackage) != 0 {
|
||||||
|
handlerMap[node.HandlerPackageAlias] = node.HandlerPackage
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
root.DFS(0, hook)
|
||||||
|
router.HandlerPackages = handlerMap
|
||||||
|
}
|
||||||
|
|
||||||
if err := pkgGen.TemplateGenerator.Generate(router, routerTplName, router.FilePath, false); err != nil {
|
if err := pkgGen.TemplateGenerator.Generate(router, routerTplName, router.FilePath, false); err != nil {
|
||||||
return fmt.Errorf("generate router %s failed, err: %v", router.FilePath, err.Error())
|
return fmt.Errorf("generate router %s failed, err: %v", router.FilePath, err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,3 @@
|
||||||
// Copyright 2022 CloudWeGo Authors
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.28.0
|
// protoc-gen-go v1.28.0
|
||||||
|
@ -243,6 +229,14 @@ var file_api_proto_extTypes = []protoimpl.ExtensionInfo{
|
||||||
Tag: "bytes,50308,opt,name=baseurl",
|
Tag: "bytes,50308,opt,name=baseurl",
|
||||||
Filename: "api.proto",
|
Filename: "api.proto",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ExtendedType: (*descriptorpb.MethodOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 50309,
|
||||||
|
Name: "api.handler_path",
|
||||||
|
Tag: "bytes,50309,opt,name=handler_path",
|
||||||
|
Filename: "api.proto",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
|
ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
|
||||||
ExtensionType: (*int32)(nil),
|
ExtensionType: (*int32)(nil),
|
||||||
|
@ -311,12 +305,14 @@ var (
|
||||||
E_Param = &file_api_proto_extTypes[24] // Whether client requests take public parameters
|
E_Param = &file_api_proto_extTypes[24] // Whether client requests take public parameters
|
||||||
// optional string baseurl = 50308;
|
// optional string baseurl = 50308;
|
||||||
E_Baseurl = &file_api_proto_extTypes[25] // Baseurl used in ttnet routing
|
E_Baseurl = &file_api_proto_extTypes[25] // Baseurl used in ttnet routing
|
||||||
|
// optional string handler_path = 50309;
|
||||||
|
E_HandlerPath = &file_api_proto_extTypes[26] // handler_path specifies the path to generate the method
|
||||||
)
|
)
|
||||||
|
|
||||||
// Extension fields to descriptorpb.EnumValueOptions.
|
// Extension fields to descriptorpb.EnumValueOptions.
|
||||||
var (
|
var (
|
||||||
// optional int32 http_code = 50401;
|
// optional int32 http_code = 50401;
|
||||||
E_HttpCode = &file_api_proto_extTypes[26]
|
E_HttpCode = &file_api_proto_extTypes[27]
|
||||||
)
|
)
|
||||||
|
|
||||||
var File_api_proto protoreflect.FileDescriptor
|
var File_api_proto protoreflect.FileDescriptor
|
||||||
|
@ -416,12 +412,16 @@ var file_api_proto_rawDesc = []byte{
|
||||||
0x61, 0x6d, 0x3a, 0x3a, 0x0a, 0x07, 0x62, 0x61, 0x73, 0x65, 0x75, 0x72, 0x6c, 0x12, 0x1e, 0x2e,
|
0x61, 0x6d, 0x3a, 0x3a, 0x0a, 0x07, 0x62, 0x61, 0x73, 0x65, 0x75, 0x72, 0x6c, 0x12, 0x1e, 0x2e,
|
||||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 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, 0x84, 0x89,
|
0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x84, 0x89,
|
||||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x75, 0x72, 0x6c, 0x3a, 0x40,
|
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x75, 0x72, 0x6c, 0x3a, 0x43,
|
||||||
0x0a, 0x09, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x2e, 0x67, 0x6f,
|
0x0a, 0x0c, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1e,
|
||||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
|
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||||
0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe1,
|
0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x85,
|
||||||
0x89, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x68, 0x74, 0x74, 0x70, 0x43, 0x6f, 0x64, 0x65,
|
0x89, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x50,
|
||||||
0x42, 0x06, 0x5a, 0x04, 0x2f, 0x61, 0x70, 0x69,
|
0x61, 0x74, 0x68, 0x3a, 0x40, 0x0a, 0x09, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65,
|
||||||
|
0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||||
|
0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69,
|
||||||
|
0x6f, 0x6e, 0x73, 0x18, 0xe1, 0x89, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x68, 0x74, 0x74,
|
||||||
|
0x70, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2f, 0x61, 0x70, 0x69,
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_api_proto_goTypes = []interface{}{
|
var file_api_proto_goTypes = []interface{}{
|
||||||
|
@ -456,11 +456,12 @@ var file_api_proto_depIdxs = []int32{
|
||||||
1, // 23: api.serializer:extendee -> google.protobuf.MethodOptions
|
1, // 23: api.serializer:extendee -> google.protobuf.MethodOptions
|
||||||
1, // 24: api.param:extendee -> google.protobuf.MethodOptions
|
1, // 24: api.param:extendee -> google.protobuf.MethodOptions
|
||||||
1, // 25: api.baseurl:extendee -> google.protobuf.MethodOptions
|
1, // 25: api.baseurl:extendee -> google.protobuf.MethodOptions
|
||||||
2, // 26: api.http_code:extendee -> google.protobuf.EnumValueOptions
|
1, // 26: api.handler_path:extendee -> google.protobuf.MethodOptions
|
||||||
27, // [27:27] is the sub-list for method output_type
|
2, // 27: api.http_code:extendee -> google.protobuf.EnumValueOptions
|
||||||
27, // [27:27] is the sub-list for method input_type
|
28, // [28:28] is the sub-list for method output_type
|
||||||
27, // [27:27] is the sub-list for extension type_name
|
28, // [28:28] is the sub-list for method input_type
|
||||||
0, // [0:27] is the sub-list for extension extendee
|
28, // [28:28] is the sub-list for extension type_name
|
||||||
|
0, // [0:28] is the sub-list for extension extendee
|
||||||
0, // [0:0] is the sub-list for field type_name
|
0, // [0:0] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +477,7 @@ func file_api_proto_init() {
|
||||||
RawDescriptor: file_api_proto_rawDesc,
|
RawDescriptor: file_api_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 0,
|
NumMessages: 0,
|
||||||
NumExtensions: 27,
|
NumExtensions: 28,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
GoTypes: file_api_proto_goTypes,
|
GoTypes: file_api_proto_goTypes,
|
||||||
|
|
|
@ -36,6 +36,7 @@ extend google.protobuf.MethodOptions {
|
||||||
optional string serializer = 50306; // Serialization method
|
optional string serializer = 50306; // Serialization method
|
||||||
optional string param = 50307; // Whether client requests take public parameters
|
optional string param = 50307; // Whether client requests take public parameters
|
||||||
optional string baseurl = 50308; // Baseurl used in ttnet routing
|
optional string baseurl = 50308; // Baseurl used in ttnet routing
|
||||||
|
optional string handler_path = 50309; // handler_path specifies the path to generate the method
|
||||||
}
|
}
|
||||||
|
|
||||||
extend google.protobuf.EnumValueOptions {
|
extend google.protobuf.EnumValueOptions {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/cloudwego/hertz/cmd/hz/internal/generator"
|
"github.com/cloudwego/hertz/cmd/hz/internal/generator"
|
||||||
"github.com/cloudwego/hertz/cmd/hz/internal/generator/model"
|
"github.com/cloudwego/hertz/cmd/hz/internal/generator/model"
|
||||||
|
"github.com/cloudwego/hertz/cmd/hz/internal/protobuf/api"
|
||||||
"github.com/cloudwego/hertz/cmd/hz/internal/util"
|
"github.com/cloudwego/hertz/cmd/hz/internal/util"
|
||||||
"github.com/cloudwego/hertz/cmd/hz/internal/util/logs"
|
"github.com/cloudwego/hertz/cmd/hz/internal/util/logs"
|
||||||
"github.com/jhump/protoreflect/desc"
|
"github.com/jhump/protoreflect/desc"
|
||||||
|
@ -121,6 +122,13 @@ func astToService(ast *descriptorpb.FileDescriptorProto, resolver *Resolver) ([]
|
||||||
}
|
}
|
||||||
path := vpath.(string)
|
path := vpath.(string)
|
||||||
|
|
||||||
|
var handlerOutDir string
|
||||||
|
genPath := checkFirstOption(api.E_HandlerPath, m.GetOptions())
|
||||||
|
handlerOutDir, ok := genPath.(string)
|
||||||
|
if !ok || len(handlerOutDir) == 0 {
|
||||||
|
handlerOutDir = ""
|
||||||
|
}
|
||||||
|
|
||||||
reqName := m.GetInputType()
|
reqName := m.GetInputType()
|
||||||
sb, err := resolver.ResolveIdentifier(reqName)
|
sb, err := resolver.ResolveIdentifier(reqName)
|
||||||
reqName = util.BaseName(sb.Scope.GetOptions().GetGoPackage(), "") + "." + sb.Name
|
reqName = util.BaseName(sb.Scope.GetOptions().GetGoPackage(), "") + "." + sb.Name
|
||||||
|
@ -145,6 +153,7 @@ func astToService(ast *descriptorpb.FileDescriptorProto, resolver *Resolver) ([]
|
||||||
HTTPMethod: hmethod,
|
HTTPMethod: hmethod,
|
||||||
Path: path,
|
Path: path,
|
||||||
Serializer: serializer,
|
Serializer: serializer,
|
||||||
|
OutputDir: handlerOutDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
goOptMapAlias := make(map[string]string, 1)
|
goOptMapAlias := make(map[string]string, 1)
|
||||||
|
|
|
@ -582,8 +582,9 @@ func (plugin *Plugin) genHttpPackage(ast *descriptorpb.FileDescriptorProto, deps
|
||||||
TemplateGenerator: generator.TemplateGenerator{
|
TemplateGenerator: generator.TemplateGenerator{
|
||||||
OutputDir: args.OutDir,
|
OutputDir: args.OutDir,
|
||||||
},
|
},
|
||||||
ProjPackage: pkg,
|
ProjPackage: pkg,
|
||||||
Options: options,
|
Options: options,
|
||||||
|
HandlerByMethod: args.HandlerByMethod,
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.ModelBackend != "" {
|
if args.ModelBackend != "" {
|
||||||
|
|
|
@ -70,6 +70,17 @@ func astToService(ast *parser.Thrift, resolver *Resolver) ([]*generator.Service,
|
||||||
if len(rs) > 1 {
|
if len(rs) > 1 {
|
||||||
return nil, fmt.Errorf("too many 'api.XXX' annotations: %s", rs)
|
return nil, fmt.Errorf("too many 'api.XXX' annotations: %s", rs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var handlerOutDir string
|
||||||
|
genPaths := getAnnotation(m.Annotations, ApiGenPath)
|
||||||
|
if len(genPaths) == 0 {
|
||||||
|
handlerOutDir = ""
|
||||||
|
} else if len(genPaths) > 1 {
|
||||||
|
return nil, fmt.Errorf("too many 'api.handler_path' for %s", m.Name)
|
||||||
|
} else {
|
||||||
|
handlerOutDir = genPaths[0]
|
||||||
|
}
|
||||||
|
|
||||||
hmethod, path := util.GetFirstKV(rs)
|
hmethod, path := util.GetFirstKV(rs)
|
||||||
if len(path) != 1 || path[0] == "" {
|
if len(path) != 1 || path[0] == "" {
|
||||||
return nil, fmt.Errorf("invalid api.%s for %s.%s: %s", hmethod, s.Name, m.Name, path)
|
return nil, fmt.Errorf("invalid api.%s for %s.%s: %s", hmethod, s.Name, m.Name, path)
|
||||||
|
@ -103,6 +114,7 @@ func astToService(ast *parser.Thrift, resolver *Resolver) ([]*generator.Service,
|
||||||
ReturnTypeName: respName,
|
ReturnTypeName: respName,
|
||||||
Path: path[0],
|
Path: path[0],
|
||||||
Serializer: sr,
|
Serializer: sr,
|
||||||
|
OutputDir: handlerOutDir,
|
||||||
// Annotations: m.Annotations,
|
// Annotations: m.Annotations,
|
||||||
}
|
}
|
||||||
refs := resolver.ExportReferred(false, true)
|
refs := resolver.ExportReferred(false, true)
|
||||||
|
|
|
@ -90,6 +90,10 @@ func (plugin *Plugin) Run() int {
|
||||||
options := CheckTagOption(plugin.args)
|
options := CheckTagOption(plugin.args)
|
||||||
|
|
||||||
pkgInfo, err := plugin.getPackageInfo()
|
pkgInfo, err := plugin.getPackageInfo()
|
||||||
|
if err != nil {
|
||||||
|
logs.Errorf("get http package info failed: %s", err.Error())
|
||||||
|
return meta.PluginError
|
||||||
|
}
|
||||||
|
|
||||||
cf, _ := util.GetColonPair(args.CustomizePackage)
|
cf, _ := util.GetColonPair(args.CustomizePackage)
|
||||||
pkg, err := args.GetGoPackage()
|
pkg, err := args.GetGoPackage()
|
||||||
|
@ -126,8 +130,9 @@ func (plugin *Plugin) Run() int {
|
||||||
TemplateGenerator: generator.TemplateGenerator{
|
TemplateGenerator: generator.TemplateGenerator{
|
||||||
OutputDir: args.OutDir,
|
OutputDir: args.OutDir,
|
||||||
},
|
},
|
||||||
ProjPackage: pkg,
|
ProjPackage: pkg,
|
||||||
Options: options,
|
Options: options,
|
||||||
|
HandlerByMethod: args.HandlerByMethod,
|
||||||
}
|
}
|
||||||
if args.ModelBackend != "" {
|
if args.ModelBackend != "" {
|
||||||
sg.Backend = meta.Backend(args.ModelBackend)
|
sg.Backend = meta.Backend(args.ModelBackend)
|
||||||
|
|
|
@ -56,6 +56,7 @@ const (
|
||||||
ApiAny = "api.any"
|
ApiAny = "api.any"
|
||||||
ApiPath = "api.path"
|
ApiPath = "api.path"
|
||||||
ApiSerializer = "api.serializer"
|
ApiSerializer = "api.serializer"
|
||||||
|
ApiGenPath = "api.handler_path"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -70,6 +71,10 @@ var (
|
||||||
ApiAny: "ANY",
|
ApiAny: "ANY",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpMethodOptionAnnotations = map[string]string{
|
||||||
|
ApiGenPath: "handler_path",
|
||||||
|
}
|
||||||
|
|
||||||
BindingTags = map[string]string{
|
BindingTags = map[string]string{
|
||||||
AnnotationPath: "path",
|
AnnotationPath: "path",
|
||||||
AnnotationQuery: "query",
|
AnnotationQuery: "query",
|
||||||
|
|
|
@ -366,8 +366,9 @@ func SubDir(root, subPkg string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
uniquePackageName = map[string]bool{}
|
uniquePackageName = map[string]bool{}
|
||||||
uniqueMiddlewareName = map[string]bool{}
|
uniqueMiddlewareName = map[string]bool{}
|
||||||
|
uniqueHandlerPackageName = map[string]bool{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetPackageUniqueName can get a non-repeating variable name for package alias
|
// GetPackageUniqueName can get a non-repeating variable name for package alias
|
||||||
|
@ -390,6 +391,15 @@ func GetMiddlewareUniqueName(name string) (string, error) {
|
||||||
return name, nil
|
return name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetHandlerPackageUniqueName(name string) (string, error) {
|
||||||
|
name, err := getUniqueName(name, uniqueHandlerPackageName)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("can not generate unique handler package name: '%s', err: %v", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
// getUniqueName can get a non-repeating variable name
|
// getUniqueName can get a non-repeating variable name
|
||||||
func getUniqueName(name string, uniqueNameSet map[string]bool) (string, error) {
|
func getUniqueName(name string, uniqueNameSet map[string]bool) (string, error) {
|
||||||
uniqueName := name
|
uniqueName := name
|
||||||
|
|
Loading…
Reference in New Issue