4 Star 6 Fork 3

王军 / golib

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
autoroute.go 6.83 KB
一键复制 编辑 原始数据 按行查看 历史
王军 提交于 2023-11-19 16:06 . 增加通用方法
package autoroute
import (
"crypto/tls"
"encoding/json"
"fmt"
"html/template"
"log"
"net"
"net/http"
"os"
"reflect"
"runtime"
"strings"
"time"
"gitee.com/haodreams/golib/logs"
"github.com/gin-gonic/gin"
)
// Setup initialize
func Setup(engine *gin.Engine) {
engine.SetFuncMap(template.FuncMap{
"str2html": Str2html,
})
}
// Str2html Convert string to template.HTML type.
func Str2html(raw string) template.HTML {
return template.HTML(raw)
}
// RunListener 自动选择HTTP 或者 HTTPS服务
// certFile, keyFile 不可用时以http启动,否则 以 tls启动
func RunListener(listener net.Listener, engine *gin.Engine, certFile, keyFile string) (err error) {
//自动增加内置函数获取当前时间
engine.GET("/status/now", func(c *gin.Context) {
c.String(200, time.Now().Format("2006-01-02 15:04:05.999")) //自动获取当前时间,可以用于心跳检测
})
//自动增加内置函数获取当前时间
uptime := time.Now().Format("2006-01-02 15:04:05")
engine.GET("/status/uptime", func(c *gin.Context) {
c.String(200, uptime) //自动获取服务启动时间
})
useTLS := false
if certFile != "" && keyFile != "" {
if _, err := os.Stat(certFile); err == nil {
if _, err = os.Stat(keyFile); err == nil {
useTLS = true
}
}
}
if useTLS { //使用加密
server := &http.Server{}
server.Handler = engine
server.TLSConfig = &tls.Config{
MinVersion: tls.VersionTLS12, // 设置最小TLS版本为TLS 1.2
CipherSuites: []uint16{
// 禁用DES相关的密码套件
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
},
}
err = server.ServeTLS(listener, certFile, keyFile)
} else {
err = engine.RunListener(listener)
}
return
}
// Normal Get & Post
func Normal(engine *gin.Engine, relativePath string, router AutoRouter, handlers ...gin.HandlerFunc) {
handlers = append(handlers, AutoRoute(router))
engine.GET(relativePath, handlers...)
engine.POST(relativePath, handlers...)
}
// AutoRouter 自动路由接口
type AutoRouter interface {
//初始化 context
Setup(c *gin.Context, controllerName string) error
}
func stackTrace() []byte {
buf := make([]byte, 1024)
for {
n := runtime.Stack(buf, false)
if n < len(buf) {
return buf[:n]
}
buf = make([]byte, 2*len(buf))
}
}
// StackTrace 栈信息
func StackTrace() string {
stack := ""
data := stackTrace()
lines := strings.Split(string(data), "\n")
for i := range lines {
if i > 0 && i < 9 {
continue
}
stack += lines[i] + "\n"
}
return stack
}
// GetStackTraceInfo 获取堆栈信息
func GetStackTraceInfo(msg string) (info string) {
info = fmt.Sprintln("GO Version:", runtime.Version())
info += fmt.Sprintln("ARCH:", runtime.GOARCH)
info += fmt.Sprintln("OS:", runtime.GOOS)
info += fmt.Sprintln("Number CPU:", runtime.NumCPU())
info += fmt.Sprintln("Routine:", runtime.NumGoroutine())
m := runtime.MemStats{}
runtime.ReadMemStats(&m)
if m.Alloc < 1024 {
info += fmt.Sprintf("Malloc memory: %d bytes\n", m.Alloc)
} else if m.Alloc < 1024*1024 {
info += fmt.Sprintf("Malloc memory: %.3f K bytes\n", float64(m.Alloc)/1024)
} else {
info += fmt.Sprintf("Malloc memory: %.3f M bytes\n", float64(m.Alloc)/1024/1024)
}
info += "\n" + msg + "\n" + StackTrace()
return
}
// AutoRoute 自动路由设置,URL 路径名称要小写
// prefix 表示需要关联的前缀
// controller 控制器类
func AutoRoute(controller AutoRouter) func(*gin.Context) {
typ := reflect.TypeOf(controller)
elem := typ.Elem()
controllerName := strings.ToLower(elem.Name())
controllerName = strings.TrimSuffix(controllerName, "controller")
m := map[string]reflect.Value{}
for i := 0; i < typ.NumMethod(); i++ {
method := typ.Method(i)
if method.Type.NumOut() != 0 {
continue
}
if method.Type.NumIn() != 1 {
continue
}
methodName := strings.ToLower(method.Name)
m[methodName] = method.Func
}
return func(c *gin.Context) {
url := c.Param("path")
url = strings.ToLower(url)
upath := strings.SplitN(url, "/", 3)
if len(upath) < 2 {
c.JSON(http.StatusNotFound, gin.H{
"code": 404,
"msg": "404, page not exists!",
})
return
}
upath[1] = strings.TrimSuffix(upath[1], ".html")
if f, ok := m[upath[1]]; ok {
defer func() {
if err := recover(); err != nil {
var brokenPipe bool
if ne, ok := err.(*net.OpError); ok {
if se, ok := ne.Err.(*os.SyscallError); ok {
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
brokenPipe = true
}
}
}
if brokenPipe {
c.Error(err.(error)) // nolint: errcheck
c.Abort()
} else {
log.Println("AutoRoute() panic:\n", GetStackTraceInfo(fmt.Sprint(err)))
c.String(501, fmt.Sprint(err)+GetStackTraceInfo(fmt.Sprint(err)))
}
}
}()
in := make([]reflect.Value, 1)
obj := reflect.New(elem)
route, ok := obj.Interface().(AutoRouter)
if !ok {
log.Println("error type")
return
}
err := route.Setup(c, controllerName)
if err != nil {
c.JSON(http.StatusPreconditionFailed, gin.H{
"code": 412,
"msg": err.Error(),
})
return
}
in[0] = obj
f.Call(in)
return
}
c.JSON(http.StatusNotFound, gin.H{
"code": 404,
"msg": "404, page not exists!",
})
}
}
/**
* @description: 生成json数据
* @param {*gin.Context} c
* @param {interface{}} data
* @param {string} msg
* @param {...int} code
* @return {*}
*/
func DataMsg(c *gin.Context, data interface{}, msg string, code ...int) {
m := map[string]any{}
m["data"] = data
m["msg"] = msg
if len(code) > 0 {
m["code"] = code[0]
} else {
m["code"] = http.StatusOK
}
c.Writer.Header().Set("Content-Type", "application/json; charset=utf-8")
jsonBytes, err := json.Marshal(m)
if err != nil {
logs.Warn(err)
return
}
_, err = c.Writer.Write(jsonBytes)
if err != nil {
logs.Warn(err)
return
}
}
func DefaultUploadHtml(writer gin.ResponseWriter, extend string) {
html := `<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>上传文件</title></head>
<body><form method="post" enctype="multipart/form-data">
%s
<input type="file" name="file" value="" /> <input type="submit" name="submit" />
</form></body></html>`
writer.Header().Add("Content-Type", "text/html")
writer.WriteHeader(200)
writer.Write([]byte(fmt.Sprintf(html, extend)))
}
Go
1
https://gitee.com/haodreams/golib.git
git@gitee.com:haodreams/golib.git
haodreams
golib
golib
7a2a333d4463

搜索帮助