157 lines
2.6 KiB
Go
157 lines
2.6 KiB
Go
package web
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
"time"
|
|
|
|
"dyproxy/providers/db"
|
|
|
|
"github.com/fsnotify/fsnotify"
|
|
"github.com/gofiber/fiber/v3"
|
|
"github.com/gofiber/fiber/v3/middleware/logger"
|
|
"github.com/gofiber/fiber/v3/middleware/recover"
|
|
"github.com/rogeecn/fabfile"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
var users map[string]string = map[string]string{
|
|
"rogeecn": "xixi@0202",
|
|
}
|
|
|
|
type Config struct {
|
|
Version string
|
|
Path string
|
|
Static string
|
|
}
|
|
|
|
var config *Config
|
|
|
|
func load(f string) error {
|
|
viper.SetConfigFile(f)
|
|
viper.SetConfigType("yaml")
|
|
|
|
if err := viper.ReadInConfig(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := viper.Unmarshal(&config); err != nil {
|
|
return err
|
|
}
|
|
|
|
viper.WatchConfig()
|
|
viper.OnConfigChange(func(e fsnotify.Event) {
|
|
if e.Op != fsnotify.Write {
|
|
return
|
|
}
|
|
|
|
if err := viper.Unmarshal(&config); err != nil {
|
|
log.Println(err)
|
|
}
|
|
log.Printf("config changed: %+v", config)
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func ServeE(cmd *cobra.Command, args []string) error {
|
|
logrus.SetLevel(logrus.WarnLevel)
|
|
|
|
conf, err := cmd.Flags().GetString("config")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := load(conf); err != nil {
|
|
return err
|
|
}
|
|
|
|
db, err := db.Connect(fabfile.MustFind("data.db"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer db.Close()
|
|
|
|
return New(
|
|
WithDB(db),
|
|
WithLogger(),
|
|
WithRecover(),
|
|
WithRoutes(),
|
|
WithPendingCleaner(),
|
|
).Serve(9090)
|
|
}
|
|
|
|
type Option func(*WebServer)
|
|
|
|
func WithDB(db *sql.DB) Option {
|
|
return func(p *WebServer) {
|
|
p.db = db
|
|
}
|
|
}
|
|
|
|
func WithLogger() Option {
|
|
return func(s *WebServer) {
|
|
s.engine.Use(logger.New())
|
|
}
|
|
}
|
|
|
|
// WithRecover
|
|
func WithRecover() Option {
|
|
return func(s *WebServer) {
|
|
s.engine.Use(recover.New())
|
|
}
|
|
}
|
|
|
|
type WebServer struct {
|
|
db *sql.DB
|
|
engine *fiber.App
|
|
|
|
local *time.Location
|
|
pendingItems map[int32]time.Time
|
|
listLock sync.RWMutex
|
|
}
|
|
|
|
func New(opts ...Option) *WebServer {
|
|
cstSh, _ := time.LoadLocation("Asia/Shanghai")
|
|
s := &WebServer{
|
|
engine: fiber.New(),
|
|
local: cstSh,
|
|
}
|
|
|
|
for _, opt := range opts {
|
|
opt(s)
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// run
|
|
func (p *WebServer) Serve(port uint) error {
|
|
log.Printf("server start serve at: :%d", port)
|
|
return p.engine.Listen(fmt.Sprintf(":%d", port))
|
|
}
|
|
|
|
func WithPendingCleaner() Option {
|
|
return func(s *WebServer) {
|
|
if s.pendingItems == nil {
|
|
s.pendingItems = make(map[int32]time.Time)
|
|
}
|
|
|
|
go func() {
|
|
for range time.NewTicker(time.Minute * 1).C {
|
|
s.listLock.Lock()
|
|
for k, v := range s.pendingItems {
|
|
if time.Since(v) > time.Minute*2 {
|
|
delete(s.pendingItems, k)
|
|
}
|
|
}
|
|
s.listLock.Unlock()
|
|
}
|
|
}()
|
|
}
|
|
}
|