|
package cmd |
|
|
|
import ( |
|
"context" |
|
"errors" |
|
"fmt" |
|
"net" |
|
"net/http" |
|
"os" |
|
"os/signal" |
|
"strconv" |
|
"sync" |
|
"syscall" |
|
"time" |
|
|
|
"github.com/alist-org/alist/v3/cmd/flags" |
|
"github.com/alist-org/alist/v3/internal/bootstrap" |
|
"github.com/alist-org/alist/v3/internal/conf" |
|
"github.com/alist-org/alist/v3/pkg/utils" |
|
"github.com/alist-org/alist/v3/server" |
|
"github.com/gin-gonic/gin" |
|
log "github.com/sirupsen/logrus" |
|
"github.com/spf13/cobra" |
|
) |
|
|
|
|
|
var ServerCmd = &cobra.Command{ |
|
Use: "server", |
|
Short: "Start the server at the specified address", |
|
Long: `Start the server at the specified address |
|
the address is defined in config file`, |
|
Run: func(cmd *cobra.Command, args []string) { |
|
Init() |
|
if conf.Conf.DelayedStart != 0 { |
|
utils.Log.Infof("delayed start for %d seconds", conf.Conf.DelayedStart) |
|
time.Sleep(time.Duration(conf.Conf.DelayedStart) * time.Second) |
|
} |
|
bootstrap.InitOfflineDownloadTools() |
|
bootstrap.LoadStorages() |
|
bootstrap.InitTaskManager() |
|
if !flags.Debug && !flags.Dev { |
|
gin.SetMode(gin.ReleaseMode) |
|
} |
|
r := gin.New() |
|
r.Use(gin.LoggerWithWriter(log.StandardLogger().Out), gin.RecoveryWithWriter(log.StandardLogger().Out)) |
|
server.Init(r) |
|
var httpSrv, httpsSrv, unixSrv *http.Server |
|
if conf.Conf.Scheme.HttpPort != -1 { |
|
httpBase := fmt.Sprintf("%s:%d", conf.Conf.Scheme.Address, conf.Conf.Scheme.HttpPort) |
|
utils.Log.Infof("start HTTP server @ %s", httpBase) |
|
httpSrv = &http.Server{Addr: httpBase, Handler: r} |
|
go func() { |
|
err := httpSrv.ListenAndServe() |
|
if err != nil && !errors.Is(err, http.ErrServerClosed) { |
|
utils.Log.Fatalf("failed to start http: %s", err.Error()) |
|
} |
|
}() |
|
} |
|
if conf.Conf.Scheme.HttpsPort != -1 { |
|
httpsBase := fmt.Sprintf("%s:%d", conf.Conf.Scheme.Address, conf.Conf.Scheme.HttpsPort) |
|
utils.Log.Infof("start HTTPS server @ %s", httpsBase) |
|
httpsSrv = &http.Server{Addr: httpsBase, Handler: r} |
|
go func() { |
|
err := httpsSrv.ListenAndServeTLS(conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile) |
|
if err != nil && !errors.Is(err, http.ErrServerClosed) { |
|
utils.Log.Fatalf("failed to start https: %s", err.Error()) |
|
} |
|
}() |
|
} |
|
if conf.Conf.Scheme.UnixFile != "" { |
|
utils.Log.Infof("start unix server @ %s", conf.Conf.Scheme.UnixFile) |
|
unixSrv = &http.Server{Handler: r} |
|
go func() { |
|
listener, err := net.Listen("unix", conf.Conf.Scheme.UnixFile) |
|
if err != nil { |
|
utils.Log.Fatalf("failed to listen unix: %+v", err) |
|
} |
|
|
|
mode, err := strconv.ParseUint(conf.Conf.Scheme.UnixFilePerm, 8, 32) |
|
if err != nil { |
|
utils.Log.Errorf("failed to parse socket file permission: %+v", err) |
|
} else { |
|
err = os.Chmod(conf.Conf.Scheme.UnixFile, os.FileMode(mode)) |
|
if err != nil { |
|
utils.Log.Errorf("failed to chmod socket file: %+v", err) |
|
} |
|
} |
|
err = unixSrv.Serve(listener) |
|
if err != nil && !errors.Is(err, http.ErrServerClosed) { |
|
utils.Log.Fatalf("failed to start unix: %s", err.Error()) |
|
} |
|
}() |
|
} |
|
if conf.Conf.S3.Port != -1 && conf.Conf.S3.Enable { |
|
s3r := gin.New() |
|
s3r.Use(gin.LoggerWithWriter(log.StandardLogger().Out), gin.RecoveryWithWriter(log.StandardLogger().Out)) |
|
server.InitS3(s3r) |
|
s3Base := fmt.Sprintf("%s:%d", conf.Conf.Scheme.Address, conf.Conf.S3.Port) |
|
utils.Log.Infof("start S3 server @ %s", s3Base) |
|
go func() { |
|
var err error |
|
if conf.Conf.S3.SSL { |
|
httpsSrv = &http.Server{Addr: s3Base, Handler: s3r} |
|
err = httpsSrv.ListenAndServeTLS(conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile) |
|
} |
|
if !conf.Conf.S3.SSL { |
|
httpSrv = &http.Server{Addr: s3Base, Handler: s3r} |
|
err = httpSrv.ListenAndServe() |
|
} |
|
if err != nil && !errors.Is(err, http.ErrServerClosed) { |
|
utils.Log.Fatalf("failed to start s3 server: %s", err.Error()) |
|
} |
|
}() |
|
} |
|
|
|
|
|
quit := make(chan os.Signal, 1) |
|
|
|
|
|
|
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) |
|
<-quit |
|
utils.Log.Println("Shutdown server...") |
|
Release() |
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) |
|
defer cancel() |
|
var wg sync.WaitGroup |
|
if conf.Conf.Scheme.HttpPort != -1 { |
|
wg.Add(1) |
|
go func() { |
|
defer wg.Done() |
|
if err := httpSrv.Shutdown(ctx); err != nil { |
|
utils.Log.Fatal("HTTP server shutdown err: ", err) |
|
} |
|
}() |
|
} |
|
if conf.Conf.Scheme.HttpsPort != -1 { |
|
wg.Add(1) |
|
go func() { |
|
defer wg.Done() |
|
if err := httpsSrv.Shutdown(ctx); err != nil { |
|
utils.Log.Fatal("HTTPS server shutdown err: ", err) |
|
} |
|
}() |
|
} |
|
if conf.Conf.Scheme.UnixFile != "" { |
|
wg.Add(1) |
|
go func() { |
|
defer wg.Done() |
|
if err := unixSrv.Shutdown(ctx); err != nil { |
|
utils.Log.Fatal("Unix server shutdown err: ", err) |
|
} |
|
}() |
|
} |
|
wg.Wait() |
|
utils.Log.Println("Server exit") |
|
}, |
|
} |
|
|
|
func init() { |
|
RootCmd.AddCommand(ServerCmd) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
func OutAlistInit() { |
|
var ( |
|
cmd *cobra.Command |
|
args []string |
|
) |
|
ServerCmd.Run(cmd, args) |
|
} |
|
|