Files
olons_server/internal/app/app.go
T

101 lines
2.8 KiB
Go

package app
import (
"context"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"git.118im.com/im_team/im_workbench/internal/accounts"
"git.118im.com/im_team/im_workbench/internal/auth"
"git.118im.com/im_team/im_workbench/internal/config"
"git.118im.com/im_team/im_workbench/internal/finance"
"git.118im.com/im_team/im_workbench/internal/httpapi"
"git.118im.com/im_team/im_workbench/internal/mall"
"git.118im.com/im_team/im_workbench/internal/portal"
"git.118im.com/im_team/im_workbench/internal/store"
"git.118im.com/im_team/im_workbench/internal/tasks"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/redis/go-redis/v9"
)
type App struct {
store *store.Store
redis *redis.Client
api *httpapi.API
frontendPath string
}
func New(cfg *config.Config) (*App, error) {
st, err := store.Open(cfg.MySQL)
if err != nil {
return nil, err
}
redisClient := redis.NewClient(&redis.Options{
Addr: cfg.Redis.Addr, Username: cfg.Redis.Username, Password: cfg.Redis.Password, DB: cfg.Redis.DB,
})
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := redisClient.Ping(ctx).Err(); err != nil {
_ = redisClient.Close()
_ = st.Close()
return nil, err
}
authenticator := auth.New(cfg.Auth, redisClient)
accountService := accounts.New(st, redisClient, cfg.Auth)
portalService := portal.New(st)
taskService := tasks.New(st)
mallService := mall.New(st)
financeService := finance.New(st, redisClient, cfg.Auth)
return &App{store: st, redis: redisClient, api: httpapi.New(authenticator, accountService, portalService, taskService, mallService, financeService), frontendPath: cfg.FrontendDir}, nil
}
func (a *App) Handler() http.Handler {
mux := http.NewServeMux()
if a.frontendDir() != "" {
mux.Handle("/admin", frontendHandler(a.frontendDir()))
mux.Handle("/admin/", frontendHandler(a.frontendDir()))
}
mux.HandleFunc("/healthz", a.api.Healthz)
mux.Handle("/metrics", promhttp.Handler())
a.api.Register(mux)
return mux
}
func (a *App) frontendDir() string {
if dir := strings.TrimSpace(os.Getenv("WORKBENCH_FRONTEND_DIR")); dir != "" {
return dir
}
return strings.TrimSpace(a.frontendPath)
}
func frontendHandler(dir string) http.Handler {
files := http.FileServer(http.Dir(dir))
index := filepath.Join(dir, "index.html")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
path := strings.TrimPrefix(r.URL.Path, "/admin")
if path == "" {
path = "/"
}
candidate := filepath.Join(dir, filepath.Clean(path))
if info, err := os.Stat(candidate); err == nil && !info.IsDir() {
r2 := r.Clone(r.Context())
r2.URL.Path = path
files.ServeHTTP(w, r2)
return
}
http.ServeFile(w, r, index)
})
}
func (a *App) Close() {
if a.redis != nil {
_ = a.redis.Close()
}
if a.store != nil {
_ = a.store.Close()
}
}