clashapi: Allow to update external UI from API

This commit is contained in:
安容 2025-04-25 10:31:55 +08:00
parent afde16ef64
commit b366ac2319
No known key found for this signature in database
GPG Key ID: 371272B5791F81D8
3 changed files with 28 additions and 0 deletions

View File

@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/sagernet/sing-box/experimental/clashapi/trafficontrol" "github.com/sagernet/sing-box/experimental/clashapi/trafficontrol"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json" "github.com/sagernet/sing/common/json"
"github.com/sagernet/ws" "github.com/sagernet/ws"
"github.com/sagernet/ws/wsutil" "github.com/sagernet/ws/wsutil"
@ -20,6 +21,7 @@ import (
func (s *Server) setupMetaAPI(r chi.Router) { func (s *Server) setupMetaAPI(r chi.Router) {
r.Get("/memory", memory(s.trafficManager)) r.Get("/memory", memory(s.trafficManager))
r.Mount("/group", groupRouter(s)) r.Mount("/group", groupRouter(s))
r.Post("/upgrade/ui", updateExternalUI(s))
} }
type Memory struct { type Memory struct {
@ -77,3 +79,25 @@ func memory(trafficManager *trafficontrol.Manager) func(w http.ResponseWriter, r
} }
} }
} }
func updateExternalUI(server *Server) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if server.externalUI == "" {
render.Status(r, http.StatusNotImplemented)
render.JSON(w, r, newError("not set external UI"))
return
}
err := server.downloadExternalUI()
if err != nil {
server.logger.Error(E.Cause(err, "download external ui"))
render.Status(r, http.StatusInternalServerError)
render.JSON(w, r, newError(err.Error()))
return
}
render.JSON(w, r, render.M{"status": "ok"})
if flusher, isFlusher := w.(http.Flusher); isFlusher {
flusher.Flush()
}
server.logger.Info("updated external UI")
}
}

View File

@ -9,6 +9,7 @@ import (
"os" "os"
"runtime" "runtime"
"strings" "strings"
"sync"
"syscall" "syscall"
"time" "time"
@ -57,6 +58,7 @@ type Server struct {
externalUI string externalUI string
externalUIDownloadURL string externalUIDownloadURL string
externalUIDownloadDetour string externalUIDownloadDetour string
externalUIAccess sync.Mutex
} }
func NewServer(ctx context.Context, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) { func NewServer(ctx context.Context, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {

View File

@ -37,6 +37,8 @@ func (s *Server) checkAndDownloadExternalUI() {
} }
func (s *Server) downloadExternalUI() error { func (s *Server) downloadExternalUI() error {
s.externalUIAccess.Lock()
defer s.externalUIAccess.Unlock()
var downloadURL string var downloadURL string
if s.externalUIDownloadURL != "" { if s.externalUIDownloadURL != "" {
downloadURL = s.externalUIDownloadURL downloadURL = s.externalUIDownloadURL