Add sing-box API service

This commit is contained in:
世界
2026-06-11 21:11:10 +08:00
parent fca959f62a
commit a485967957
36 changed files with 2075 additions and 849 deletions
+7 -22
View File
@@ -14,17 +14,15 @@ import (
"github.com/sagernet/cors"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/trafficcontrol"
"github.com/sagernet/sing-box/common/urltest"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/experimental"
"github.com/sagernet/sing-box/experimental/clashapi/trafficontrol"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/cleanup"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/observable"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/filemanager"
@@ -50,10 +48,9 @@ type Server struct {
endpoint adapter.EndpointManager
logger log.Logger
httpServer *http.Server
trafficManager *trafficontrol.Manager
trafficManager *trafficcontrol.Manager
urlTestHistory adapter.URLTestHistoryStorage
logDebug bool
cleaner *cleanup.Cleaner
mode string
modeList []string
@@ -66,7 +63,10 @@ type Server struct {
}
func NewServer(ctx context.Context, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
trafficManager := trafficontrol.NewManager()
trafficManager := service.PtrFromContext[trafficcontrol.Manager](ctx)
if trafficManager == nil {
return nil, E.New("missing traffic manager")
}
chiRouter := chi.NewRouter()
s := &Server{
ctx: ctx,
@@ -86,7 +86,6 @@ func NewServer(ctx context.Context, logFactory log.ObservableFactory, options op
externalController: options.ExternalController != "",
externalUIDownloadURL: options.ExternalUIDownloadURL,
externalUIDownloadDetour: options.ExternalUIDownloadDetour,
cleaner: cleanup.Add(trafficManager.Clear),
}
s.urlTestHistory = service.FromContext[adapter.URLTestHistoryStorage](ctx)
if s.urlTestHistory == nil {
@@ -196,9 +195,7 @@ func (s *Server) Start(stage adapter.StartStage) error {
func (s *Server) Close() error {
return common.Close(
common.PtrOrNil(s.httpServer),
s.trafficManager,
s.urlTestHistory,
common.PtrOrNil(s.cleaner),
)
}
@@ -245,18 +242,6 @@ func (s *Server) HistoryStorage() adapter.URLTestHistoryStorage {
return s.urlTestHistory
}
func (s *Server) TrafficManager() *trafficontrol.Manager {
return s.trafficManager
}
func (s *Server) RoutedConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, matchedRule adapter.Rule, matchOutbound adapter.Outbound) net.Conn {
return trafficontrol.NewTCPTracker(conn, s.trafficManager, metadata, s.outbound, matchedRule, matchOutbound)
}
func (s *Server) RoutedPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, matchedRule adapter.Rule, matchOutbound adapter.Outbound) N.PacketConn {
return trafficontrol.NewUDPTracker(conn, s.trafficManager, metadata, s.outbound, matchedRule, matchOutbound)
}
func authentication(serverSecret string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
@@ -309,7 +294,7 @@ type Traffic struct {
Down int64 `json:"down"`
}
func traffic(ctx context.Context, trafficManager *trafficontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
func traffic(ctx context.Context, trafficManager *trafficcontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var conn net.Conn
if r.Header.Get("Upgrade") == "websocket" {