Add filemanager api
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package experimental
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -8,7 +9,7 @@ import (
|
||||
"github.com/sagernet/sing-box/option"
|
||||
)
|
||||
|
||||
type ClashServerConstructor = func(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error)
|
||||
type ClashServerConstructor = func(ctx context.Context, router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error)
|
||||
|
||||
var clashServerConstructor ClashServerConstructor
|
||||
|
||||
@@ -16,9 +17,9 @@ func RegisterClashServerConstructor(constructor ClashServerConstructor) {
|
||||
clashServerConstructor = constructor
|
||||
}
|
||||
|
||||
func NewClashServer(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
||||
func NewClashServer(ctx context.Context, router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
||||
if clashServerConstructor == nil {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
return clashServerConstructor(router, logFactory, options)
|
||||
return clashServerConstructor(ctx, router, logFactory, options)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/service/filemanager"
|
||||
"github.com/sagernet/websocket"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -37,6 +38,7 @@ func init() {
|
||||
var _ adapter.ClashServer = (*Server)(nil)
|
||||
|
||||
type Server struct {
|
||||
ctx context.Context
|
||||
router adapter.Router
|
||||
logger log.Logger
|
||||
httpServer *http.Server
|
||||
@@ -53,10 +55,11 @@ type Server struct {
|
||||
externalUIDownloadDetour string
|
||||
}
|
||||
|
||||
func NewServer(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
||||
func NewServer(ctx context.Context, router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
||||
trafficManager := trafficontrol.NewManager()
|
||||
chiRouter := chi.NewRouter()
|
||||
server := &Server{
|
||||
ctx: ctx,
|
||||
router: router,
|
||||
logger: logFactory.NewLogger("clash-api"),
|
||||
httpServer: &http.Server{
|
||||
@@ -82,7 +85,7 @@ func NewServer(router adapter.Router, logFactory log.ObservableFactory, options
|
||||
if foundPath, loaded := C.FindPath(cachePath); loaded {
|
||||
cachePath = foundPath
|
||||
} else {
|
||||
cachePath = C.BasePath(cachePath)
|
||||
cachePath = filemanager.BasePath(ctx, cachePath)
|
||||
}
|
||||
server.cacheFilePath = cachePath
|
||||
}
|
||||
@@ -113,7 +116,7 @@ func NewServer(router adapter.Router, logFactory log.ObservableFactory, options
|
||||
server.setupMetaAPI(r)
|
||||
})
|
||||
if options.ExternalUI != "" {
|
||||
server.externalUI = C.BasePath(os.ExpandEnv(options.ExternalUI))
|
||||
server.externalUI = filemanager.BasePath(ctx, os.ExpandEnv(options.ExternalUI))
|
||||
chiRouter.Group(func(r chi.Router) {
|
||||
fs := http.StripPrefix("/ui", http.FileServer(http.Dir(server.externalUI)))
|
||||
r.Get("/ui", http.RedirectHandler("/ui/", http.StatusTemporaryRedirect).ServeHTTP)
|
||||
|
||||
@@ -12,11 +12,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/service/filemanager"
|
||||
)
|
||||
|
||||
func (s *Server) checkAndDownloadExternalUI() {
|
||||
@@ -79,7 +79,7 @@ func (s *Server) downloadExternalUI() error {
|
||||
}
|
||||
|
||||
func (s *Server) downloadZIP(name string, body io.Reader, output string) error {
|
||||
tempFile, err := C.CreateTemp(name)
|
||||
tempFile, err := filemanager.CreateTemp(s.ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (s *Server) downloadZIP(name string, body io.Reader, output string) error {
|
||||
return err
|
||||
}
|
||||
savePath := filepath.Join(saveDirectory, pathElements[len(pathElements)-1])
|
||||
err = downloadZIPEntry(file, savePath)
|
||||
err = downloadZIPEntry(s.ctx, file, savePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -120,8 +120,8 @@ func (s *Server) downloadZIP(name string, body io.Reader, output string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadZIPEntry(zipFile *zip.File, savePath string) error {
|
||||
saveFile, err := os.Create(savePath)
|
||||
func downloadZIPEntry(ctx context.Context, zipFile *zip.File, savePath string) error {
|
||||
saveFile, err := filemanager.Create(ctx, savePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -27,3 +27,27 @@ func RedirectStderr(path string) error {
|
||||
stderrFile = outputFile
|
||||
return nil
|
||||
}
|
||||
|
||||
func RedirectStderrAsUser(path string, uid, gid int) error {
|
||||
if stats, err := os.Stat(path); err == nil && stats.Size() > 0 {
|
||||
_ = os.Rename(path, path+".old")
|
||||
}
|
||||
outputFile, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = outputFile.Chown(uid, gid)
|
||||
if err != nil {
|
||||
outputFile.Close()
|
||||
os.Remove(outputFile.Name())
|
||||
return err
|
||||
}
|
||||
err = unix.Dup2(int(outputFile.Fd()), int(os.Stderr.Fd()))
|
||||
if err != nil {
|
||||
outputFile.Close()
|
||||
os.Remove(outputFile.Name())
|
||||
return err
|
||||
}
|
||||
stderrFile = outputFile
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/sagernet/sing/common/control"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/service/filemanager"
|
||||
)
|
||||
|
||||
type BoxService struct {
|
||||
@@ -30,6 +31,7 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
|
||||
return nil, err
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx = filemanager.WithDefault(ctx, sBasePath, sTempPath, sUserID, sGroupID)
|
||||
instance, err := box.New(box.Options{
|
||||
Context: ctx,
|
||||
Options: options,
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
package libbox
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
func SetBasePath(path string) {
|
||||
C.SetBasePath(path)
|
||||
}
|
||||
var (
|
||||
sBasePath string
|
||||
sTempPath string
|
||||
sUserID int
|
||||
sGroupID int
|
||||
)
|
||||
|
||||
func SetTempPath(path string) {
|
||||
C.SetTempPath(path)
|
||||
func Setup(basePath string, tempPath string, userID int, groupID int) {
|
||||
sBasePath = basePath
|
||||
sTempPath = tempPath
|
||||
sUserID = userID
|
||||
sGroupID = groupID
|
||||
if sUserID == -1 {
|
||||
sUserID = os.Getuid()
|
||||
}
|
||||
if sGroupID == -1 {
|
||||
sGroupID = os.Getgid()
|
||||
}
|
||||
}
|
||||
|
||||
func Version() string {
|
||||
|
||||
Reference in New Issue
Block a user