feat: add integrated web frontend
This commit is contained in:
+38
-4
@@ -3,6 +3,9 @@ package app
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.118im.com/im_team/im_workbench/internal/accounts"
|
||||
@@ -19,9 +22,10 @@ import (
|
||||
)
|
||||
|
||||
type App struct {
|
||||
store *store.Store
|
||||
redis *redis.Client
|
||||
api *httpapi.API
|
||||
store *store.Store
|
||||
redis *redis.Client
|
||||
api *httpapi.API
|
||||
frontendPath string
|
||||
}
|
||||
|
||||
func New(cfg *config.Config) (*App, error) {
|
||||
@@ -45,17 +49,47 @@ func New(cfg *config.Config) (*App, error) {
|
||||
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)}, nil
|
||||
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()
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
type Config struct {
|
||||
Listen string `json:"listen"`
|
||||
FrontendDir string `json:"frontend_dir"`
|
||||
MySQL MySQLConfig `json:"mysql"`
|
||||
Redis RedisConfig `json:"redis"`
|
||||
Auth AuthConfig `json:"auth"`
|
||||
@@ -65,7 +66,8 @@ func Load() (*Config, error) {
|
||||
|
||||
func defaultConfig() *Config {
|
||||
return &Config{
|
||||
Listen: ":6061",
|
||||
Listen: ":6061",
|
||||
FrontendDir: "web/dist",
|
||||
MySQL: MySQLConfig{
|
||||
DSN: "root:root@tcp(127.0.0.1:3306)/olons_admin?parseTime=true&charset=utf8mb4&loc=Local",
|
||||
MaxOpenConns: 15,
|
||||
@@ -85,6 +87,7 @@ func defaultConfig() *Config {
|
||||
|
||||
func applyEnv(cfg *Config) {
|
||||
setString(&cfg.Listen, "WORKBENCH_LISTEN")
|
||||
setString(&cfg.FrontendDir, "WORKBENCH_FRONTEND_DIR")
|
||||
setString(&cfg.MySQL.DSN, "WORKBENCH_MYSQL_DSN")
|
||||
setInt(&cfg.MySQL.MaxOpenConns, "WORKBENCH_MYSQL_MAX_OPEN_CONNS")
|
||||
setInt(&cfg.MySQL.MaxIdleConns, "WORKBENCH_MYSQL_MAX_IDLE_CONNS")
|
||||
|
||||
Reference in New Issue
Block a user