genroutes.go 6.1 KB

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