This commit is contained in:
新亮
2021-03-20 22:05:59 +08:00
parent 36ef904211
commit 3e918fce59
67 changed files with 7239 additions and 103 deletions
-76
View File
@@ -1,76 +0,0 @@
package router
import (
"github.com/xinliangnote/go-gin-api/internal/api/controller/demo_handler"
"github.com/xinliangnote/go-gin-api/internal/api/controller/user_handler"
"github.com/xinliangnote/go-gin-api/internal/api/router/middleware"
"github.com/xinliangnote/go-gin-api/internal/graph/handler"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"github.com/xinliangnote/go-gin-api/internal/pkg/grpc"
"github.com/xinliangnote/go-gin-api/internal/pkg/metrics"
"github.com/xinliangnote/go-gin-api/internal/pkg/notify"
"github.com/pkg/errors"
"go.uber.org/zap"
)
func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.ClientConn) (core.Mux, error) {
if logger == nil {
return nil, errors.New("logger required")
}
mux, err := core.New(logger,
core.WithEnableCors(),
core.WithEnableRate(),
core.WithPanicNotify(notify.OnPanicNotify),
core.WithRecordMetrics(metrics.RecordMetrics),
)
if err != nil {
panic(err)
}
// 中间件
middles := middleware.New(logger, cache)
// graphQL 控制器
gqlHandler := handler.New(logger, db, cache)
gql := mux.Group("/graphql")
{
gql.GET("", gqlHandler.Playground())
gql.POST("/query", gqlHandler.Query())
}
// demo 控制器
demoHandler := demo_handler.New(logger, db, cache, grpConn)
demo := mux.Group("/demo", core.WrapAuthHandler(middles.Jwt)) // 使用 jwt 验证
{
// 为了演示 Trace ,增加了一些看起来无意义的调试信息和 SQL 信息。
demo.GET("/trace", demoHandler.Trace())
// 模拟数据
demo.GET("get/:name", core.AliasForRecordMetrics("/demo/get"), demoHandler.Get())
demo.POST("post", demoHandler.Post())
}
demoNoAuth := mux.Group("/auth") // 不使用 jwt 验证
{
demoNoAuth.POST("/get", demoHandler.Auth())
}
// user 控制器
userHandler := user_handler.New(logger, db, cache)
user := mux.Group("/user", core.WrapAuthHandler(middles.Jwt))
{
user.POST("/create", userHandler.Create())
user.PUT("/update", userHandler.UpdateNickNameByID())
user.PATCH("/delete/:id", userHandler.Delete())
user.GET("/info/:username", core.AliasForRecordMetrics("/user/info"), userHandler.Detail())
}
return mux, nil
}
+7
View File
@@ -97,6 +97,9 @@ type Context interface {
GraphPayload(payload interface{})
getGraphPayload() interface{}
// HTML 返回界面
HTML(name string, obj interface{})
// AbortWithError 错误返回
AbortWithError(err errno.Error)
abortError() errno.Error
@@ -251,6 +254,10 @@ func (c *context) GraphPayload(payload interface{}) {
c.ctx.Set(_GraphPayloadName, payload)
}
func (c *context) HTML(name string, obj interface{}) {
c.ctx.HTML(200, name+".html", obj)
}
func (c *context) Header() http.Header {
header := c.ctx.Request.Header
+3
View File
@@ -246,6 +246,9 @@ func New(logger *zap.Logger, options ...Option) (Mux, error) {
fmt.Println(color.Green(fmt.Sprintf("* [register port %s]", configs.ProjectPort())))
fmt.Println(color.Green(fmt.Sprintf("* [register env %s]", env.Active().Value())))
mux.engine.StaticFS("bootstrap", http.Dir("./assets/bootstrap"))
mux.engine.LoadHTMLGlob("./assets/templates/**/*")
// withoutLogPaths 这些请求,默认不记录日志
withoutTracePaths := map[string]bool{
"/metrics": true,
@@ -0,0 +1,9 @@
package middleware
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
func (m *middleware) DisableLog() core.HandlerFunc {
return func(c core.Context) {
core.DisableTrace(c)
}
}
@@ -1,10 +1,8 @@
package middleware
import (
"github.com/xinliangnote/go-gin-api/internal/api/service/user_service"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/grpc"
"github.com/xinliangnote/go-gin-api/pkg/errno"
"go.uber.org/zap"
@@ -21,13 +19,14 @@ type Middleware interface {
// Resubmit 中间件
Resubmit() core.HandlerFunc
// DisableLog 不记录日志
DisableLog() core.HandlerFunc
}
type middleware struct {
logger *zap.Logger
cache cache.Repo
grpConn grpc.ClientConn
userService user_service.UserService
logger *zap.Logger
cache cache.Repo
}
func New(logger *zap.Logger, cache cache.Repo) Middleware {
+60
View File
@@ -0,0 +1,60 @@
package router
import (
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"github.com/xinliangnote/go-gin-api/internal/pkg/grpc"
"github.com/xinliangnote/go-gin-api/internal/pkg/metrics"
"github.com/xinliangnote/go-gin-api/internal/pkg/notify"
"github.com/xinliangnote/go-gin-api/internal/router/middleware"
"github.com/pkg/errors"
"go.uber.org/zap"
)
type resource struct {
mux core.Mux
logger *zap.Logger
db db.Repo
cache cache.Repo
grpConn grpc.ClientConn
middles middleware.Middleware
}
func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo, grpConn grpc.ClientConn) (core.Mux, error) {
if logger == nil {
return nil, errors.New("logger required")
}
mux, err := core.New(logger,
core.WithEnableCors(),
core.WithEnableRate(),
core.WithPanicNotify(notify.OnPanicNotify),
core.WithRecordMetrics(metrics.RecordMetrics),
)
if err != nil {
panic(err)
}
r := new(resource)
r.mux = mux
r.logger = logger
r.db = db
r.cache = cache
r.grpConn = grpConn
r.middles = middleware.New(logger, cache)
// 设置 WEB 路由
setWebRouter(r)
// 设置 API 路由
setApiRouter(r)
// 设置 GraphQL 路由
setGraphQLRouter(r)
return mux, nil
}
+36
View File
@@ -0,0 +1,36 @@
package router
import (
"github.com/xinliangnote/go-gin-api/internal/api/controller/demo_handler"
"github.com/xinliangnote/go-gin-api/internal/api/controller/user_handler"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
func setApiRouter(r *resource) {
// demo 控制器
demoHandler := demo_handler.New(r.logger, r.db, r.cache, r.grpConn)
demo := r.mux.Group("/demo", core.WrapAuthHandler(r.middles.Jwt)) // 使用 jwt 验证
{
// 为了演示 Trace ,增加了一些看起来无意义的调试信息和 SQL 信息。
demo.GET("/trace", demoHandler.Trace())
// 模拟数据
demo.GET("get/:name", core.AliasForRecordMetrics("/demo/get"), demoHandler.Get())
demo.POST("post", demoHandler.Post())
}
demoNoAuth := r.mux.Group("/auth") // 不使用 jwt 验证
{
demoNoAuth.POST("/get", demoHandler.Auth())
}
// user 控制器
userHandler := user_handler.New(r.logger, r.db, r.cache)
user := r.mux.Group("/user", core.WrapAuthHandler(r.middles.Jwt))
{
user.POST("/create", userHandler.Create())
user.PUT("/update", userHandler.UpdateNickNameByID())
user.PATCH("/delete/:id", userHandler.Delete())
user.GET("/info/:username", core.AliasForRecordMetrics("/user/info"), userHandler.Detail())
}
}
+14
View File
@@ -0,0 +1,14 @@
package router
import "github.com/xinliangnote/go-gin-api/internal/graph/handler"
func setGraphQLRouter(r *resource) {
// graphQL 控制器
gqlHandler := handler.New(r.logger, r.db, r.cache)
gql := r.mux.Group("/graphql")
{
gql.GET("", gqlHandler.Playground())
gql.POST("/query", gqlHandler.Query())
}
}
+39
View File
@@ -0,0 +1,39 @@
package router
import (
"github.com/xinliangnote/go-gin-api/internal/web/controller/configinfo_handler"
"github.com/xinliangnote/go-gin-api/internal/web/controller/dashboard_handler"
"github.com/xinliangnote/go-gin-api/internal/web/controller/gencode_handler"
"github.com/xinliangnote/go-gin-api/internal/web/controller/index_handler"
)
func setWebRouter(r *resource) {
indexHandler := index_handler.New(r.logger, r.db, r.cache)
dashboardHandler := dashboard_handler.New(r.logger, r.db, r.cache)
genCodeHandler := gencode_handler.New(r.logger, r.db, r.cache)
configInfoHandler := configinfo_handler.New(r.logger, r.db, r.cache)
web := r.mux.Group("", r.middles.DisableLog())
{
// 首页侧边栏
web.GET("", indexHandler.View())
// 仪表盘
web.GET("/dashboard", dashboardHandler.View())
// 配置信息
web.GET("/configinfo", configInfoHandler.View())
// 代码生成
web.GET("/init", genCodeHandler.InitView())
web.POST("/init_exec", genCodeHandler.InitExecute())
web.GET("/gormgen", genCodeHandler.GormView())
web.POST("/gormgen_exec", genCodeHandler.GormExecute())
web.GET("/handlergen", genCodeHandler.HandlerView())
web.POST("/handlergen_exec", genCodeHandler.HandlerExecute())
}
}
@@ -0,0 +1,12 @@
package configinfo_handler
import (
"github.com/xinliangnote/go-gin-api/configs"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
func (h *handler) View() core.HandlerFunc {
return func(c core.Context) {
c.HTML("configinfo", configs.Get())
}
}
@@ -0,0 +1,31 @@
package configinfo_handler
import (
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"go.uber.org/zap"
)
var _ Handler = (*handler)(nil)
type Handler interface {
i()
View() core.HandlerFunc
}
type handler struct {
logger *zap.Logger
cache cache.Repo
}
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
return &handler{
logger: logger,
cache: cache,
}
}
func (h *handler) i() {}
@@ -0,0 +1,89 @@
package dashboard_handler
import (
"fmt"
"os"
"runtime"
"strconv"
"strings"
"time"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/pkg/env"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/host"
"github.com/shirou/gopsutil/mem"
)
const (
B = 1
KB = 1024 * B
MB = 1024 * KB
GB = 1024 * MB
)
type viewResponse struct {
MemTotal string
MemUsed string
MemUsedPercent float64
DiskTotal string
DiskUsed string
DiskUsedPercent float64
HostOS string
HostName string
CpuName string
CpuCores int32
CpuUsedPercent float64
GoPath string
GoVersion string
Goroutine int
ProjectPath string
Env string
Host string
GoOS string
GoArch string
}
func (h *handler) View() core.HandlerFunc {
return func(c core.Context) {
memInfo, _ := mem.VirtualMemory()
diskInfo, _ := disk.Usage("/")
hostInfo, _ := host.Info()
cpuInfo, _ := cpu.Info()
cpuPercent, _ := cpu.Percent(time.Second, false)
obj := new(viewResponse)
obj.MemTotal = fmt.Sprintf("%d GB", memInfo.Total/GB)
obj.MemUsed = fmt.Sprintf("%d GB", memInfo.Used/GB)
obj.MemUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", memInfo.UsedPercent), 64)
obj.DiskTotal = fmt.Sprintf("%d GB", diskInfo.Total/GB)
obj.DiskUsed = fmt.Sprintf("%d GB", diskInfo.Used/GB)
obj.DiskUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", diskInfo.UsedPercent), 64)
obj.HostOS = fmt.Sprintf("%s(%s) %s", hostInfo.Platform, hostInfo.PlatformFamily, hostInfo.PlatformVersion)
obj.HostName = hostInfo.Hostname
obj.CpuName = cpuInfo[0].ModelName
obj.CpuCores = cpuInfo[0].Cores
obj.CpuUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", cpuPercent[0]), 64)
obj.GoPath = runtime.GOROOT()
obj.GoVersion = runtime.Version()
obj.Goroutine = runtime.NumGoroutine()
dir, _ := os.Getwd()
obj.ProjectPath = strings.Replace(dir, "\\", "/", -1)
obj.Host = c.Host()
obj.Env = env.Active().Value()
obj.GoOS = runtime.GOOS
obj.GoArch = runtime.GOARCH
c.HTML("dashboard", obj)
}
}
@@ -0,0 +1,31 @@
package dashboard_handler
import (
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"go.uber.org/zap"
)
var _ Handler = (*handler)(nil)
type Handler interface {
i()
View() core.HandlerFunc
}
type handler struct {
logger *zap.Logger
cache cache.Repo
}
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
return &handler{
logger: logger,
cache: cache,
}
}
func (h *handler) i() {}
@@ -0,0 +1,44 @@
package gencode_handler
import (
"bytes"
"fmt"
"os/exec"
"github.com/xinliangnote/go-gin-api/configs"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
type gormExecuteRequest struct {
Tables string `form:"tables"`
}
func (h *handler) GormExecute() core.HandlerFunc {
return func(c core.Context) {
req := new(gormExecuteRequest)
if err := c.ShouldBindPostForm(req); err != nil {
c.Payload("参数传递有误")
return
}
mysqlConf := configs.Get().MySQL.Read
shellPath := fmt.Sprintf("./scripts/gormgen.sh %s %s %s %s %s", mysqlConf.Addr, mysqlConf.User, mysqlConf.Pass, mysqlConf.Name, req.Tables)
command := exec.Command("/bin/bash", "-c", shellPath) //初始化 Cmd
// windows 版本
//command := exec.Command("cmd", "/C", shellPath)
var stderr bytes.Buffer
command.Stderr = &stderr
output, err := command.Output()
if err != nil {
c.Payload(stderr.String())
return
}
c.Payload(string(output))
}
}
@@ -0,0 +1,42 @@
package gencode_handler
import (
"fmt"
"github.com/xinliangnote/go-gin-api/configs"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
func (h *handler) GormView() core.HandlerFunc {
return func(c core.Context) {
type tableInfo struct {
Name string `db:"table_name"` // name
Comment string `db:"table_comment"` // comment
}
var tableCollect []tableInfo
mysqlConf := configs.Get().MySQL.Read
sqlTables := fmt.Sprintf("SELECT `table_name`,`table_comment` FROM `information_schema`.`tables` WHERE `table_schema`= '%s'", mysqlConf.Name)
rows, err := h.db.GetDbR().Raw(sqlTables).Rows()
if err != nil {
c.HTML("gormgen", tableCollect)
return
}
defer rows.Close()
for rows.Next() {
var info tableInfo
err = rows.Scan(&info.Name, &info.Comment)
if err != nil {
fmt.Printf("execute query tables action error,had ignored, detail is [%v]\n", err.Error())
continue
}
tableCollect = append(tableCollect, info)
}
c.HTML("gencode_gorm", tableCollect)
}
}
@@ -0,0 +1,40 @@
package gencode_handler
import (
"bytes"
"fmt"
"os/exec"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
type handlerExecuteRequest struct {
Name string `form:"name"`
}
func (h *handler) HandlerExecute() core.HandlerFunc {
return func(c core.Context) {
req := new(handlerExecuteRequest)
if err := c.ShouldBindPostForm(req); err != nil {
c.Payload("参数传递有误")
return
}
shellPath := fmt.Sprintf("./scripts/handlergen.sh %s", req.Name)
command := exec.Command("/bin/bash", "-c", shellPath) //初始化 Cmd
// windows 版本
//command := exec.Command("cmd", "/C", shellPath)
var stderr bytes.Buffer
command.Stderr = &stderr
output, err := command.Output()
if err != nil {
c.Payload(stderr.String())
return
}
c.Payload(string(output))
}
}
@@ -0,0 +1,11 @@
package gencode_handler
import (
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
func (h *handler) HandlerView() core.HandlerFunc {
return func(c core.Context) {
c.HTML("gencode_handler", nil)
}
}
@@ -0,0 +1,33 @@
package gencode_handler
import (
"bytes"
"fmt"
"os/exec"
"github.com/xinliangnote/go-gin-api/configs"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
)
func (h *handler) InitExecute() core.HandlerFunc {
return func(c core.Context) {
mysqlConf := configs.Get().MySQL.Read
shellPath := fmt.Sprintf("./scripts/init.sh %s %s %s %s", mysqlConf.Addr, mysqlConf.User, mysqlConf.Pass, mysqlConf.Name)
command := exec.Command("/bin/bash", "-c", shellPath) //初始化 Cmd
// windows 版本
//command := exec.Command("cmd", "/C", shellPath)
var stderr bytes.Buffer
command.Stderr = &stderr
output, err := command.Output()
if err != nil {
c.Payload(stderr.String())
return
}
c.Payload(string(output))
}
}
@@ -0,0 +1,9 @@
package gencode_handler
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
func (h *handler) InitView() core.HandlerFunc {
return func(c core.Context) {
c.HTML("gencode_init", nil)
}
}
@@ -0,0 +1,40 @@
package gencode_handler
import (
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"go.uber.org/zap"
)
var _ Handler = (*handler)(nil)
type Handler interface {
i()
InitView() core.HandlerFunc
InitExecute() core.HandlerFunc
HandlerView() core.HandlerFunc
HandlerExecute() core.HandlerFunc
GormView() core.HandlerFunc
GormExecute() core.HandlerFunc
}
type handler struct {
db db.Repo
logger *zap.Logger
cache cache.Repo
}
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
return &handler{
logger: logger,
cache: cache,
db: db,
}
}
func (h *handler) i() {}
@@ -0,0 +1,9 @@
package index_handler
import "github.com/xinliangnote/go-gin-api/internal/pkg/core"
func (h *handler) View() core.HandlerFunc {
return func(c core.Context) {
c.HTML("index", nil)
}
}
@@ -0,0 +1,31 @@
package index_handler
import (
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"go.uber.org/zap"
)
var _ Handler = (*handler)(nil)
type Handler interface {
i()
View() core.HandlerFunc
}
type handler struct {
logger *zap.Logger
cache cache.Repo
}
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Handler {
return &handler{
logger: logger,
cache: cache,
}
}
func (h *handler) i() {}