5 Commits

Author SHA1 Message Date
127c57dc3a refactor: rename timeout ctx 2025-07-15 11:43:15 +08:00
d6b0b8ea36 fix: api opt setting 2025-07-15 11:18:54 +08:00
23d7841ccf feat: 添加提示语 2025-07-15 10:45:05 +08:00
247490c35d fix: resp 多参数问题 2025-07-14 11:16:34 +08:00
fad0b852cb feat: 修改 api 为 option 模式设置; 添加 healthz handler 2025-07-11 11:52:53 +08:00
7 changed files with 146 additions and 40 deletions

View File

@ -4,34 +4,89 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors" "errors"
"gitea.loveuer.com/yizhisec/packages/handler"
"gitea.loveuer.com/yizhisec/packages/logger" "gitea.loveuer.com/yizhisec/packages/logger"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net" "net"
"net/http" "net/http"
) )
type Api struct { type Option func(*option)
Address string
Name string type option struct {
App *gin.Engine name string
TlsConfig *tls.Config version string
address string
app *gin.Engine
tlsConfig *tls.Config
} }
func New(ctx context.Context, api *Api) (func(context.Context) error, error) { func WithName(name string) Option {
return func(o *option) {
if name != "" {
o.name = name
}
}
}
func WithVersion(version string) Option {
return func(o *option) {
if version != "" {
o.version = version
}
}
}
func WithAddress(address string) Option {
return func(o *option) {
if address != "" {
o.address = address
}
}
}
func WithApp(app *gin.Engine) Option {
return func(o *option) {
if app != nil {
o.app = app
}
}
}
func WithTLSConfig(tlsConfig *tls.Config) Option {
return func(o *option) {
if tlsConfig != nil {
o.tlsConfig = tlsConfig
}
}
}
func New(ctx context.Context, optFns ...Option) (func(context.Context) error, error) {
var ( var (
err error err error
fn func(context.Context) error fn func(context.Context) error
ln net.Listener ln net.Listener
opt = &option{
name: "unknown",
version: "v0.0.1",
address: "127.0.0.1:9119",
tlsConfig: nil,
}
) )
if api == nil { for _, ofn := range optFns {
return fn, errors.New("api is nil") ofn(opt)
} }
if api.TlsConfig != nil { if opt.app == nil {
ln, err = tls.Listen("tcp", api.Address, api.TlsConfig) opt.app = gin.Default()
opt.app.GET("/healthz", handler.Healthz(opt.name, opt.version))
}
if opt.tlsConfig != nil {
ln, err = tls.Listen("tcp", opt.address, opt.tlsConfig)
} else { } else {
ln, err = net.Listen("tcp", api.Address) ln, err = net.Listen("tcp", opt.address)
} }
if err != nil { if err != nil {
@ -39,11 +94,11 @@ func New(ctx context.Context, api *Api) (func(context.Context) error, error) {
} }
svc := &http.Server{ svc := &http.Server{
Handler: api.App, Handler: opt.app,
} }
go func() { go func() {
logger.InfoCtx(ctx, "[%s] api svc running at: %s", api.Name, api.Address) logger.InfoCtx(ctx, "[%s] api svc running at: %s", opt.name, opt.address)
if err = svc.Serve(ln); err != nil { if err = svc.Serve(ln); err != nil {
if !errors.Is(err, http.ErrServerClosed) { if !errors.Is(err, http.ErrServerClosed) {
logger.ErrorCtx(ctx, "api svc run failed, err = %s", err.Error()) logger.ErrorCtx(ctx, "api svc run failed, err = %s", err.Error())
@ -52,7 +107,7 @@ func New(ctx context.Context, api *Api) (func(context.Context) error, error) {
}() }()
fn = func(timeout context.Context) error { fn = func(timeout context.Context) error {
logger.WarnCtx(ctx, "[%s] api svc shutdown...", api.Name) logger.WarnCtx(ctx, "[%s] api svc shutdown...", opt.name)
return svc.Shutdown(timeout) return svc.Shutdown(timeout)
} }

View File

@ -45,7 +45,7 @@ func New(opts ...OptionFn) (Cache, error) {
Password: password, Password: password,
}) })
if err = client.Ping(tool.CtxTimeout(cfg.ctx, 5)).Err(); err != nil { if err = client.Ping(tool.TimeoutCtx(cfg.ctx, 5)).Err(); err != nil {
return nil, err return nil, err
} }

19
handler/healthz.go Normal file
View File

@ -0,0 +1,19 @@
package handler
import (
"gitea.loveuer.com/yizhisec/packages/resp"
"github.com/gin-gonic/gin"
"time"
)
func Healthz(name, version string) gin.HandlerFunc {
start := time.Now()
return func(c *gin.Context) {
resp.R200(c, gin.H{
"name": name,
"version": version,
"start_at": start,
"uptime": time.Since(start).String(),
})
}
}

View File

@ -5,6 +5,7 @@ const (
Msg400 = "参数错误" Msg400 = "参数错误"
Msg401 = "该账号登录已失效, 请重新登录" Msg401 = "该账号登录已失效, 请重新登录"
Msg401NoMulti = "用户已在其他地方登录" Msg401NoMulti = "用户已在其他地方登录"
Msg401Inactive = "当前用户尚未生效, 请稍后再试"
Msg403 = "权限不足" Msg403 = "权限不足"
Msg404 = "资源不存在" Msg404 = "资源不存在"
Msg500 = "服务器开小差了" Msg500 = "服务器开小差了"

View File

@ -43,22 +43,44 @@ func RE(c *gin.Context, err error) {
func _r(c *gin.Context, r *res, args ...any) { func _r(c *gin.Context, r *res, args ...any) {
length := len(args) length := len(args)
switch length {
case 0: if length == 0 {
break goto END
case 1:
if msg, ok := args[0].(string); ok {
r.Msg = msg
} }
case 2:
r.Data = args[1] if length >= 4 {
case 3: goto H4
r.Err = args[2] }
case 4:
if length >= 3 {
goto H3
}
if length >= 2 {
goto H2
}
if length >= 1 {
goto H1
}
H4:
if code, err := cast.ToIntE(args[3]); err == nil { if code, err := cast.ToIntE(args[3]); err == nil {
r.Code = code r.Code = code
} }
H3:
if es, ok := args[2].(error); ok {
r.Err = es.Error()
} else {
r.Err = args[2]
} }
H2:
r.Data = args[1]
H1:
if msg, ok := args[0].(string); ok {
r.Msg = msg
}
END:
if r.Msg == "" { if r.Msg == "" {
r.Msg = Msg(r.Status) r.Msg = Msg(r.Status)

9
resp/resp_test.go Normal file
View File

@ -0,0 +1,9 @@
package resp
import (
"testing"
)
func TestResp(t *testing.T) {
}

View File

@ -23,7 +23,7 @@ func Timeout(seconds ...int) (ctx context.Context) {
return return
} }
func CtxTimeout(ctx context.Context, seconds ...int) context.Context { func TimeoutCtx(ctx context.Context, seconds ...int) context.Context {
var ( var (
duration time.Duration duration time.Duration
) )