genroutes.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. package gogen
  2. import (
  3. "fmt"
  4. "os"
  5. "path"
  6. "sort"
  7. "strings"
  8. "text/template"
  9. "github.com/tal-tech/go-zero/core/collection"
  10. "github.com/tal-tech/go-zero/tools/goctl/api/spec"
  11. "github.com/tal-tech/go-zero/tools/goctl/config"
  12. "github.com/tal-tech/go-zero/tools/goctl/util"
  13. "github.com/tal-tech/go-zero/tools/goctl/util/format"
  14. "github.com/tal-tech/go-zero/tools/goctl/vars"
  15. )
  16. const (
  17. routesFilename = "routes"
  18. routesTemplate = `// Code generated by goctl. DO NOT EDIT.
  19. package handler
  20. import (
  21. "net/http"
  22. {{.importPackages}}
  23. )
  24. func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
  25. {{.routesAdditions}}
  26. }
  27. `
  28. routesAdditionTemplate = `
  29. server.AddRoutes(
  30. {{.routes}} {{.jwt}}{{.signature}} {{.prefix}}
  31. )
  32. `
  33. )
  34. var mapping = map[string]string{
  35. "delete": "http.MethodDelete",
  36. "get": "http.MethodGet",
  37. "head": "http.MethodHead",
  38. "post": "http.MethodPost",
  39. "put": "http.MethodPut",
  40. "patch": "http.MethodPatch",
  41. "connect": "http.MethodConnect",
  42. "options": "http.MethodOptions",
  43. "trace": "http.MethodTrace",
  44. }
  45. type (
  46. group struct {
  47. routes []route
  48. jwtEnabled bool
  49. signatureEnabled bool
  50. authName string
  51. middlewares []string
  52. prefix string
  53. }
  54. route struct {
  55. method string
  56. path string
  57. handler string
  58. }
  59. )
  60. func genRoutes(dir, rootPkg string, cfg *config.Config, api *spec.ApiSpec) error {
  61. var builder strings.Builder
  62. groups, err := getRoutes(api)
  63. if err != nil {
  64. return err
  65. }
  66. gt := template.Must(template.New("groupTemplate").Parse(routesAdditionTemplate))
  67. for _, g := range groups {
  68. var gbuilder strings.Builder
  69. gbuilder.WriteString("[]rest.Route{")
  70. for _, r := range g.routes {
  71. fmt.Fprintf(&gbuilder, `
  72. {
  73. Method: %s,
  74. Path: "%s",
  75. Handler: %s,
  76. },`,
  77. r.method, r.path, r.handler)
  78. }
  79. var jwt string
  80. if g.jwtEnabled {
  81. jwt = fmt.Sprintf("\n rest.WithJwt(serverCtx.Config.%s.AccessSecret),", g.authName)
  82. }
  83. var signature, prefix string
  84. if g.signatureEnabled {
  85. signature = "\n rest.WithSignature(serverCtx.Config.Signature),"
  86. }
  87. if len(g.prefix) > 0 {
  88. prefix = fmt.Sprintf(`
  89. rest.WithPrefix("%s"),`, g.prefix)
  90. }
  91. var routes string
  92. if len(g.middlewares) > 0 {
  93. gbuilder.WriteString("\n}...,")
  94. params := g.middlewares
  95. for i := range params {
  96. params[i] = "serverCtx." + params[i]
  97. }
  98. middlewareStr := strings.Join(params, ", ")
  99. routes = fmt.Sprintf("rest.WithMiddlewares(\n[]rest.Middleware{ %s }, \n %s \n),",
  100. middlewareStr, strings.TrimSpace(gbuilder.String()))
  101. } else {
  102. gbuilder.WriteString("\n},")
  103. routes = strings.TrimSpace(gbuilder.String())
  104. }
  105. if err := gt.Execute(&builder, map[string]string{
  106. "routes": routes,
  107. "jwt": jwt,
  108. "signature": signature,
  109. "prefix": prefix,
  110. }); err != nil {
  111. return err
  112. }
  113. }
  114. routeFilename, err := format.FileNamingFormat(cfg.NamingFormat, routesFilename)
  115. if err != nil {
  116. return err
  117. }
  118. routeFilename = routeFilename + ".go"
  119. filename := path.Join(dir, handlerDir, routeFilename)
  120. os.Remove(filename)
  121. return genFile(fileGenConfig{
  122. dir: dir,
  123. subdir: handlerDir,
  124. filename: routeFilename,
  125. templateName: "routesTemplate",
  126. category: "",
  127. templateFile: "",
  128. builtinTemplate: routesTemplate,
  129. data: map[string]string{
  130. "importPackages": genRouteImports(rootPkg, api),
  131. "routesAdditions": strings.TrimSpace(builder.String()),
  132. },
  133. })
  134. }
  135. func genRouteImports(parentPkg string, api *spec.ApiSpec) string {
  136. importSet := collection.NewSet()
  137. importSet.AddStr(fmt.Sprintf("\"%s\"", util.JoinPackages(parentPkg, contextDir)))
  138. for _, group := range api.Service.Groups {
  139. for _, route := range group.Routes {
  140. folder := route.GetAnnotation(groupProperty)
  141. if len(folder) == 0 {
  142. folder = group.GetAnnotation(groupProperty)
  143. if len(folder) == 0 {
  144. continue
  145. }
  146. }
  147. importSet.AddStr(fmt.Sprintf("%s \"%s\"", toPrefix(folder), util.JoinPackages(parentPkg, handlerDir, folder)))
  148. }
  149. }
  150. imports := importSet.KeysStr()
  151. sort.Strings(imports)
  152. projectSection := strings.Join(imports, "\n\t")
  153. depSection := fmt.Sprintf("\"%s/rest\"", vars.ProjectOpenSourceURL)
  154. return fmt.Sprintf("%s\n\n\t%s", projectSection, depSection)
  155. }
  156. func getRoutes(api *spec.ApiSpec) ([]group, error) {
  157. var routes []group
  158. for _, g := range api.Service.Groups {
  159. var groupedRoutes group
  160. for _, r := range g.Routes {
  161. handler := getHandlerName(r)
  162. handler = handler + "(serverCtx)"
  163. folder := r.GetAnnotation(groupProperty)
  164. if len(folder) > 0 {
  165. handler = toPrefix(folder) + "." + strings.ToUpper(handler[:1]) + handler[1:]
  166. } else {
  167. folder = g.GetAnnotation(groupProperty)
  168. if len(folder) > 0 {
  169. handler = toPrefix(folder) + "." + strings.ToUpper(handler[:1]) + handler[1:]
  170. }
  171. }
  172. groupedRoutes.routes = append(groupedRoutes.routes, route{
  173. method: mapping[r.Method],
  174. path: r.Path,
  175. handler: handler,
  176. })
  177. }
  178. jwt := g.GetAnnotation("jwt")
  179. if len(jwt) > 0 {
  180. groupedRoutes.authName = jwt
  181. groupedRoutes.jwtEnabled = true
  182. }
  183. signature := g.GetAnnotation("signature")
  184. if signature == "true" {
  185. groupedRoutes.signatureEnabled = true
  186. }
  187. middleware := g.GetAnnotation("middleware")
  188. if len(middleware) > 0 {
  189. groupedRoutes.middlewares = append(groupedRoutes.middlewares,
  190. strings.Split(middleware, ",")...)
  191. }
  192. prefix := g.GetAnnotation(spec.RoutePrefixKey)
  193. prefix = strings.ReplaceAll(prefix, `"`, "")
  194. prefix = strings.TrimSpace(prefix)
  195. if len(prefix) > 0 {
  196. prefix = path.Join("/", prefix)
  197. groupedRoutes.prefix = prefix
  198. }
  199. routes = append(routes, groupedRoutes)
  200. }
  201. return routes, nil
  202. }
  203. func toPrefix(folder string) string {
  204. return strings.ReplaceAll(folder, "/", "")
  205. }