-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
196 lines (178 loc) · 5.63 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package main
import (
"embed"
"flag"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
"github.com/junlongzzz/file-download-agent/common"
"github.com/junlongzzz/file-download-agent/handler"
)
var (
downloadHandler *handler.DownloadHandler
webDavHandler *handler.WebDavHandler
staticHandler *handler.StaticHandler
//go:embed static/*
static embed.FS
)
// 程序入口执行函数
func main() {
versionInfo := fmt.Sprintf("File Download Agent v%s (%s %s/%s)", common.Version(), runtime.Version(), runtime.GOOS, runtime.GOARCH)
// 从环境变量内读取运行参数
host := os.Getenv("FDA_HOST")
port, _ := strconv.Atoi(os.Getenv("FDA_PORT"))
signKey := os.Getenv("FDA_SIGN_KEY")
dir := os.Getenv("FDA_DIR")
logLevel := os.Getenv("FDA_LOG_LEVEL")
webDavEnableEnv := os.Getenv("FDA_WEBDAV_ENABLE")
// 默认启用webdav
webDavEnable := true
if webDavEnableEnv != "" {
webDavEnable, _ = strconv.ParseBool(webDavEnableEnv)
}
webDavDir := os.Getenv("FDA_WEBDAV_DIR")
webDavUser := os.Getenv("FDA_WEBDAV_USER")
webDavPass := os.Getenv("FDA_WEBDAV_PASS")
certFile := os.Getenv("FDA_CERT_FILE")
certKeyFile := os.Getenv("FDA_CERT_KEY_FILE")
// 从运行参数中获取运行参数
// 会覆盖环境变量的值,如果不存在默认就使用环境变量内的值
flag.StringVar(&host, "host", host, "server host")
flag.IntVar(&port, "port", port, "server port")
flag.StringVar(&signKey, "sign-key", signKey, "server download sign key")
flag.StringVar(&dir, "dir", dir, "download directory, default ./files")
flag.BoolVar(&webDavEnable, "webdav-enable", webDavEnable, "enable webdav server or not")
flag.StringVar(&webDavDir, "webdav-dir", webDavDir, "webdav root directory, default use <dir>")
flag.StringVar(&webDavUser, "webdav-user", webDavUser, "webdav username, default anonymous")
flag.StringVar(&webDavPass, "webdav-pass", webDavPass, "webdav password, default md5(sign_key)")
flag.StringVar(&logLevel, "log-level", logLevel, "log level: debug, info, warn, error")
flag.StringVar(&certFile, "cert-file", certFile, "cert file path")
flag.StringVar(&certKeyFile, "cert-key-file", certKeyFile, "cert key file path")
var version bool
flag.BoolVar(&version, "version", false, "show version")
// 解析命令行参数
flag.Parse()
if version {
fmt.Println(versionInfo)
os.Exit(0)
}
// 设置日志输出级别
var slogLevel slog.Level
switch strings.ToLower(logLevel) {
case "debug":
slogLevel = slog.LevelDebug
case "info":
slogLevel = slog.LevelInfo
case "warn":
slogLevel = slog.LevelWarn
case "error":
slogLevel = slog.LevelError
default:
slogLevel = slog.LevelInfo
}
slog.SetLogLoggerLevel(slogLevel)
slog.Info(versionInfo)
if signKey != "" {
slog.Info("Sign key has been set")
}
if dir == "" {
// 默认下载目录为当前程序执行目录
executable, err := os.Executable()
if err == nil {
dir = filepath.Join(filepath.Dir(executable), "files")
// 判断文件夹是否存在,否则创建
if _, err := os.Stat(dir); os.IsNotExist(err) {
// 文件夹不存在,创建
if err := os.Mkdir(dir, os.ModePerm); err != nil {
slog.Error(fmt.Sprintf("Create directory error: %v", err))
os.Exit(1)
}
}
} else {
slog.Error(fmt.Sprintf("Get executable path error: %v", err))
os.Exit(1)
}
}
slog.Info(fmt.Sprintf("Download directory: %s", dir))
if webDavEnable {
slog.Info("WebDAV is enabled")
if webDavDir == "" {
// 未设置webdav目录,使用下载目录
webDavDir = dir
}
slog.Info(fmt.Sprintf("WebDAV directory: %s", webDavDir))
if webDavUser == "" {
// 未设置webdav用户名,使用匿名用户
webDavUser = "anonymous"
}
if webDavPass == "" && signKey != "" {
// 未设置webdav密码,使用sign_key的md5值
webDavPass = common.CalculateMD5(signKey)
}
// 初始化 webdav handler
webDavHandler = handler.NewWebDavHandler(webDavDir, webDavUser, webDavPass)
} else {
slog.Info("WebDAV is disabled")
webDavHandler = nil
}
// 初始化handler
downloadHandler = handler.NewDownloadHandler(dir, signKey)
staticHandler = handler.NewStaticHandler(static)
// 启动服务器
server(host, port, certFile, certKeyFile)
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
signalReceived := <-signalChan
slog.Info(fmt.Sprintf("Server stopped (signal: %v)", signalReceived))
os.Exit(0)
}
// 启动HTTP服务器
func server(host string, port int, certFile, keyFile string) {
if port <= 0 || port >= 65535 {
// 不合法端口号,重置为默认端口
port = 18080
}
// 创建路由器
serveMux := http.NewServeMux()
// 注册默认根路径路由
serveMux.Handle("/", staticHandler)
// 注册访问路由
serveMux.Handle("/download", downloadHandler)
if webDavHandler != nil {
serveMux.Handle("/webdav/", webDavHandler)
}
go func() {
// 启动HTTP服务器 异步
// 创建服务器
// 支持 h2c 的服务器,兼容 http/1.1
protocols := new(http.Protocols)
protocols.SetHTTP1(true)
protocols.SetHTTP2(true)
protocols.SetUnencryptedHTTP2(true)
httpServer := &http.Server{
Addr: fmt.Sprintf("%s:%d", host, port),
Handler: serveMux,
Protocols: protocols,
}
var err error
if certFile != "" && keyFile != "" {
// 支持 https 的服务器
slog.Info(fmt.Sprintf("Server is running on %s with HTTPS", httpServer.Addr))
err = httpServer.ListenAndServeTLS(certFile, keyFile)
} else {
slog.Info(fmt.Sprintf("Server is running on %s", httpServer.Addr))
err = httpServer.ListenAndServe()
}
if err != nil {
slog.Error(fmt.Sprintf("Server start error: %v", err))
os.Exit(1)
}
}()
}