Files
packages/api/api.go

116 lines
2.0 KiB
Go

package api
import (
"context"
"crypto/tls"
"errors"
"gitea.loveuer.com/yizhisec/packages/handler"
"gitea.loveuer.com/yizhisec/packages/logger"
"github.com/gin-gonic/gin"
"net"
"net/http"
)
type Option func(*option)
type option struct {
name string
version string
address string
app *gin.Engine
tlsConfig *tls.Config
}
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 (
err error
fn func(context.Context) error
ln net.Listener
opt = &option{
name: "unknown",
version: "v0.0.1",
address: "127.0.0.1:9119",
tlsConfig: nil,
}
)
for _, ofn := range optFns {
ofn(opt)
}
if opt.app == nil {
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 {
ln, err = net.Listen("tcp", opt.address)
}
if err != nil {
return fn, err
}
svc := &http.Server{
Handler: opt.app,
}
go func() {
logger.InfoCtx(ctx, "[%s] api svc running at: %s", opt.name, opt.address)
if err = svc.Serve(ln); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
logger.ErrorCtx(ctx, "api svc run failed, err = %s", err.Error())
}
}
}()
fn = func(timeout context.Context) error {
logger.WarnCtx(ctx, "[%s] api svc shutdown...", opt.name)
return svc.Shutdown(timeout)
}
return fn, nil
}