Initialize LineUp app server
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/lineup/app-server/modules"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var cfgFile string
|
||||
flag.StringVar(&cfgFile, "config", "configs/lineup.yaml", "config file")
|
||||
flag.Parse()
|
||||
|
||||
vp := viper.New()
|
||||
vp.SetConfigFile(cfgFile)
|
||||
if err := vp.ReadInConfig(); err != nil {
|
||||
fmt.Println("读取配置失败:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
vp.SetEnvPrefix("LINEUP")
|
||||
vp.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||
vp.AutomaticEnv()
|
||||
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
if vp.GetString("mode") == "debug" {
|
||||
gin.SetMode(gin.DebugMode)
|
||||
}
|
||||
|
||||
r := gin.Default()
|
||||
r.Use(corsMiddleware(vp.GetStringSlice("client.allowedOrigins")))
|
||||
|
||||
// 静态文件服务
|
||||
r.Static("/chat", "./assets/chat")
|
||||
// Markdown dependencies are served locally so the chat remains available on
|
||||
// a private network and never executes content from a third-party CDN.
|
||||
// They intentionally use their own prefix: /chat already owns a wildcard
|
||||
// static route, which Gin cannot combine with nested exact file routes.
|
||||
r.Static("/vendor/marked", "./node_modules/marked/lib")
|
||||
r.Static("/vendor/dompurify", "./node_modules/dompurify/dist")
|
||||
r.StaticFile("/", "./assets/chat/index.html")
|
||||
|
||||
// 注册模块路由
|
||||
modules.SetupRoutes(r, vp)
|
||||
|
||||
fmt.Printf("LineUp App Server 启动 → %s\n", vp.GetString("addr"))
|
||||
fmt.Printf("WuKongIM API → %s\n", vp.GetString("wukongim.apiURL"))
|
||||
r.Run(vp.GetString("addr"))
|
||||
}
|
||||
|
||||
// corsMiddleware permits only configured LineUp hosts to call the JSON API.
|
||||
// The Web reference host is served same-origin and does not need an Origin
|
||||
// header. Tauri uses its own WebView origin, so it must be explicitly allowed.
|
||||
func corsMiddleware(origins []string) gin.HandlerFunc {
|
||||
allowed := make(map[string]struct{}, len(origins))
|
||||
for _, origin := range origins {
|
||||
if origin = strings.TrimSpace(origin); origin != "" {
|
||||
allowed[origin] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return func(c *gin.Context) {
|
||||
origin := c.GetHeader("Origin")
|
||||
if origin != "" {
|
||||
if _, ok := allowed[origin]; !ok {
|
||||
if c.Request.Method == http.MethodOptions {
|
||||
c.AbortWithStatus(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
c.Header("Access-Control-Allow-Origin", origin)
|
||||
c.Header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
||||
c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-LineUp-Agent-Secret")
|
||||
c.Header("Vary", "Origin")
|
||||
}
|
||||
if c.Request.Method == http.MethodOptions {
|
||||
c.AbortWithStatus(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user