diff --git a/README.MD b/README.MD index d7e80bf0..a5cb78d4 100644 --- a/README.MD +++ b/README.MD @@ -131,68 +131,83 @@ sync-interval: 10 keepalive-timeout: 10 # 同步文件时最多打开的连接数量 download-max-conn: 64 + +# 缓存 +cache: + # 缓存类型: + # nocache: 不缓存 + # inmem: 程序内内存缓存 + # redis: Redis 缓存 + type: inmem + # 服务器上行限制 serve-limit: - # 是否启用上行限制 - enable: false - # 最大连接数量 - max-conn: 16384 - # 上行速率限制 (KiB/s), 0 表示无限制 - upload-rate: 0 + # 是否启用上行限制 + enable: false + # 最大连接数量 + max-conn: 16384 + # 上行速率限制 (KiB/s), 0 表示无限制 + upload-rate: 0 # 内置的仪表板 dashboard: - # 是否启用 - enable: true - # PWA 的名称, 在桌面设备上显示 - pwa-name: GoOpenBmclApi Dashboard - # PWA 短名称, 在移动设备上显示 - pwa-short_name: GOBA Dash - # PWA 描述 - pwa-description: Go-Openbmclapi Internal Dashboard + # 是否启用 + enable: true + # PWA 的名称, 在桌面设备上显示 + pwa-name: GoOpenBmclApi Dashboard + # PWA 短名称, 在移动设备上显示 + pwa-short_name: GOBA Dash + # PWA 描述 + pwa-description: Go-Openbmclapi Internal Dashboard # 子存储节点列表 # 注意: measure 测量请求总是以第一个存储为准 storages: - # local 为本地存储 - - type: local - # 使用该子节点的概率 (非负整数) - weight: 100 - # 节点附加数据 - data: - # cache 文件夹到路径 - cache-path: cache - # 压缩方式 (目前未使用) - compressor: "" - # mount 为网络存储 (与旧版 oss 选项含义大致相同) - - type: mount - # 使用该子节点的概率 (非负整数) - # 设为 0 将使该子节点成为备选节点 (若该节点前一个节点失效才会使用该节点), 如果所有子节点均为 0 则平均分配 - weight: 0 - # 节点附加数据 - data: - # 文件夹路径 - path: oss_mirror - # 对应的网络URL路径 - redirect-base: https://oss.example.com/base/paths - # 启动之前在 measure 子文件夹内生成 1-200MB 的测速文件 (默认为动态生成) - pre-gen-measures: false - # webdav 使用 webdav 存储 - - type: webdav - # 使用该子节点的概率 (非负整数) - weight: 100 - # 节点附加数据 - data: - # 链接到下方 webdav-users 的键值对 - alias: example-user - # Webdav 入口 URL - endpoint: ../optional/another/endpoint/ - # 用户名 - username: optional-another-username - # 密码 - password: optional-another-password - # 启动之前生成 1-200MB 的测速文件 (默认为动态生成) - pre-gen-measures: false + # local 为本地存储 + - type: local + # 使用该子节点的概率 (非负整数) + weight: 100 + # 节点附加数据 + data: + # cache 文件夹到路径 + cache-path: cache + # 压缩方式 (目前未使用) + compressor: "" + # mount 为网络存储 (与旧版 oss 选项含义大致相同) + - type: mount + # 使用该子节点的概率 (非负整数) + # 设为 0 将使该子节点成为备选节点 (若该节点前一个节点失效才会使用该节点), 如果所有子节点均为 0 则平均分配 + weight: 0 + # 节点附加数据 + data: + # 文件夹路径 + path: oss_mirror + # 对应的网络URL路径 + redirect-base: https://oss.example.com/base/paths + # 启动之前在 measure 子文件夹内生成 1-200MB 的测速文件 (默认为动态生成) + pre-gen-measures: false + # webdav 使用 webdav 存储 + - type: webdav + # + id: webdav-storage-1 + # 使用该子节点的概率 (非负整数) + weight: 100 + # 节点附加数据 + data: + # 链接到下方 webdav-users 的键值对 + alias: example-user + # 相对于 alias 中的 Webdav 入口 URL + endpoint: ../optional/another/endpoint/ + # [可选] 覆盖 alias 中的用户名 + username: optional-another-username + # [可选] 覆盖 alias 中的密码 + password: optional-another-password + # 启动之前生成 1-200MB 的测速文件 (默认为动态生成) + pre-gen-measures: false + # 设置为 true 后将跟踪 302 请求 (即不会将最终用户重定向到网盘) + follow-redirect: false + # 重定向链接缓存世界, 仅当 follow-redirect 为 false 时有用. 0 表示不缓存重定向 + redirect-link-cache: 0s webdav-users: example-user: diff --git a/config.go b/config.go index 111a81af..53c5fd09 100644 --- a/config.go +++ b/config.go @@ -40,7 +40,7 @@ type CacheConfig struct { Type string `yaml:"type"` Data any `yaml:"data,omitempty"` - newCache func() Cache + newCache func() Cache `yaml:"-"` } func (c *CacheConfig) UnmarshalYAML(n *yaml.Node) (err error) { @@ -48,7 +48,7 @@ func (c *CacheConfig) UnmarshalYAML(n *yaml.Node) (err error) { Type string `yaml:"type"` Data RawYAML `yaml:"data,omitempty"` } - if err = n.Decode(cfg); err != nil { + if err = n.Decode(&cfg); err != nil { return } c.Type = cfg.Type @@ -138,7 +138,8 @@ var defaultConfig = Config{ DownloadMaxConn: 16, Cache: CacheConfig{ - Type: "inmem", + Type: "inmem", + newCache: func() Cache { return NewInMemCache() }, }, ServeLimit: ServeLimitConfig{ @@ -292,8 +293,8 @@ func readConfig() (config Config) { ids := make(map[string]int, len(config.Storages)) for i, s := range config.Storages { if s.Id == "" { - logErrorf("Empty storage id at [%d]", i) - os.Exit(1) + s.Id = fmt.Sprintf("storage-%d", i) + config.Storages[i].Id = s.Id } if j, ok := ids[s.Id]; ok { logErrorf("Duplicated storage id %q at [%d] and [%d], please edit the config.", s.Id, i, j) diff --git a/config.yaml b/config.yaml index 35378ac8..ae523289 100644 --- a/config.yaml +++ b/config.yaml @@ -15,23 +15,33 @@ cluster-secret: ${CLUSTER_SECRET} sync-interval: 10 keepalive-timeout: 10 download-max-conn: 16 +cache: + type: inmem serve-limit: - enable: false - max-conn: 16384 - upload-rate: 10240 + enable: false + max-conn: 16384 + upload-rate: 10240 dashboard: - enable: true - pwa-name: GoOpenBmclApi Dashboard - pwa-short_name: GOBA Dash - pwa-description: Go-Openbmclapi Internal Dashboard + enable: true + pwa-name: GoOpenBmclApi Dashboard + pwa-short_name: GOBA Dash + pwa-description: Go-Openbmclapi Internal Dashboard storages: - - type: local - weight: 100 - data: - cache-path: cache - compressor: "" + - type: local + id: local-storage-0 + weight: 100 + data: + cache-path: cache + compressor: "" + - type: webdav + id: webdav-storage-1 + weight: 0 + data: + pre-gen-measures: false + follow-redirect: false + redirect-link-cache: 0s webdav-users: - example-user: - endpoint: https://webdav.example.com/path/to/endpoint/ - username: example-username - password: example-password + example-user: + endpoint: https://webdav.example.com/path/to/endpoint/ + username: example-username + password: example-password diff --git a/storage.go b/storage.go index 89e4811c..77def4a6 100644 --- a/storage.go +++ b/storage.go @@ -100,14 +100,14 @@ type BasicStorageOption struct { } type StorageOption struct { - BasicStorageOption - Data any `yaml:"data"` + BasicStorageOption `yaml:",inline"` + Data any `yaml:"data"` } func (o *StorageOption) UnmarshalYAML(n *yaml.Node) (err error) { var opts struct { - BasicStorageOption - Data RawYAML `yaml:"data"` + BasicStorageOption `yaml:",inline"` + Data RawYAML `yaml:"data"` } if err = n.Decode(&opts); err != nil { return diff --git a/storage_webdav.go b/storage_webdav.go index bc1cde46..8d5bcc6d 100644 --- a/storage_webdav.go +++ b/storage_webdav.go @@ -267,7 +267,7 @@ func copyHeader(key string, dst, src http.Header) { } func (s *WebDavStorage) ServeDownload(rw http.ResponseWriter, req *http.Request, hash string, size int64) (int64, error) { - if s.opt.RedirectLinkCache > 0 { + if !s.opt.FollowRedirect && s.opt.RedirectLinkCache > 0 { if location, ok := s.cache.Get(hash); ok { // fix the size for Ranged request rgs, err := gosrc.ParseRange(req.Header.Get("Range"), size) @@ -305,12 +305,19 @@ func (s *WebDavStorage) ServeDownload(rw http.ResponseWriter, req *http.Request, copyHeader("If-None-Match", tgReq.Header, req.Header) copyHeader("If-Match", tgReq.Header, req.Header) copyHeader("If-Range", tgReq.Header, req.Header) - resp, err := noRedirectCli.Do(tgReq) + + cli := noRedirectCli + if s.opt.FollowRedirect { + cli = http.DefaultClient + } + + resp, err := cli.Do(tgReq) if err != nil { return 0, err } defer resp.Body.Close() logDebugf("Requested %q: status=%d", target, resp.StatusCode) + rwh := rw.Header() switch resp.StatusCode / 100 { case 3: diff --git a/util.go b/util.go index 90528002..dd02cd28 100644 --- a/util.go +++ b/util.go @@ -430,7 +430,7 @@ func (d YAMLDuration) MarshalYAML() (any, error) { func (d *YAMLDuration) UnmarshalYAML(n *yaml.Node) (err error) { var v string - if err = n.Decode(v); err != nil { + if err = n.Decode(&v); err != nil { return } var td time.Duration