feat(filesystem): Support sub-directories for cdn/proxy domain
This commit is contained in:
parent
12e3f10ad7
commit
0e431eedb2
5 changed files with 51 additions and 30 deletions
|
@ -148,9 +148,9 @@ func (handler Driver) CORS() error {
|
|||
}
|
||||
|
||||
// Get 获取文件
|
||||
func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) {
|
||||
func (handler Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) {
|
||||
// 获取文件源地址
|
||||
downloadURL, err := handler.Source(ctx, path, int64(model.GetIntSetting("preview_timeout", 60)), false, 0)
|
||||
downloadURL, err := handler.Source(ctx, objectPath, int64(model.GetIntSetting("preview_timeout", 60)), false, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ func (handler Driver) Thumb(ctx context.Context, file *model.File) (*response.Co
|
|||
}
|
||||
|
||||
// Source 获取外链URL
|
||||
func (handler Driver) Source(ctx context.Context, path string, ttl int64, isDownload bool, speed int) (string, error) {
|
||||
func (handler Driver) Source(ctx context.Context, objectPath string, ttl int64, isDownload bool, speed int) (string, error) {
|
||||
// 尝试从上下文获取文件名
|
||||
fileName := ""
|
||||
if file, ok := ctx.Value(fsctx.FileModelCtx).(model.File); ok {
|
||||
|
@ -285,10 +285,10 @@ func (handler Driver) Source(ctx context.Context, path string, ttl int64, isDown
|
|||
options.ContentDescription = "attachment; filename=\"" + url.PathEscape(fileName) + "\""
|
||||
}
|
||||
|
||||
return handler.signSourceURL(ctx, path, ttl, &options)
|
||||
return handler.signSourceURL(ctx, objectPath, ttl, &options)
|
||||
}
|
||||
|
||||
func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64, options *urlOption) (string, error) {
|
||||
func (handler Driver) signSourceURL(ctx context.Context, objectPath string, ttl int64, options *urlOption) (string, error) {
|
||||
cdnURL, err := url.Parse(handler.Policy.BaseURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -296,7 +296,7 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64,
|
|||
|
||||
// 公有空间不需要签名
|
||||
if !handler.Policy.IsPrivate {
|
||||
file, err := url.Parse(path)
|
||||
file, err := url.Parse(objectPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64,
|
|||
return sourceURL.String(), nil
|
||||
}
|
||||
|
||||
presignedURL, err := handler.Client.Object.GetPresignedURL(ctx, http.MethodGet, path,
|
||||
presignedURL, err := handler.Client.Object.GetPresignedURL(ctx, http.MethodGet, objectPath,
|
||||
handler.Policy.AccessKey, handler.Policy.SecretKey, time.Duration(ttl)*time.Second, options)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -324,6 +324,10 @@ func (handler Driver) signSourceURL(ctx context.Context, path string, ttl int64,
|
|||
presignedURL.Host = cdnURL.Host
|
||||
presignedURL.Scheme = cdnURL.Scheme
|
||||
|
||||
// 支持代理域名使用子目录
|
||||
// Support sub-directories for proxy domain
|
||||
presignedURL.Path = path.Join(cdnURL.Path, presignedURL.Path)
|
||||
|
||||
return presignedURL.String(), nil
|
||||
}
|
||||
|
||||
|
@ -374,8 +378,8 @@ func (handler Driver) CancelToken(ctx context.Context, uploadSession *serializer
|
|||
}
|
||||
|
||||
// Meta 获取文件信息
|
||||
func (handler Driver) Meta(ctx context.Context, path string) (*MetaData, error) {
|
||||
res, err := handler.Client.Object.Head(ctx, path, &cossdk.ObjectHeadOptions{})
|
||||
func (handler Driver) Meta(ctx context.Context, objectPath string) (*MetaData, error) {
|
||||
res, err := handler.Client.Object.Head(ctx, objectPath, &cossdk.ObjectHeadOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||
|
@ -76,9 +77,9 @@ func (handler Driver) List(ctx context.Context, path string, recursive bool) ([]
|
|||
}
|
||||
|
||||
// Get 获取文件内容
|
||||
func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) {
|
||||
func (handler Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) {
|
||||
// 打开文件
|
||||
file, err := os.Open(util.RelativePath(path))
|
||||
file, err := os.Open(util.RelativePath(objectPath))
|
||||
if err != nil {
|
||||
util.Log().Debug("Failed to open file: %s", err)
|
||||
return nil, err
|
||||
|
@ -219,7 +220,7 @@ func (handler Driver) Thumb(ctx context.Context, file *model.File) (*response.Co
|
|||
}
|
||||
|
||||
// Source 获取外链URL
|
||||
func (handler Driver) Source(ctx context.Context, path string, ttl int64, isDownload bool, speed int) (string, error) {
|
||||
func (handler Driver) Source(ctx context.Context, objectPath string, ttl int64, isDownload bool, speed int) (string, error) {
|
||||
file, ok := ctx.Value(fsctx.FileModelCtx).(model.File)
|
||||
if !ok {
|
||||
return "", errors.New("failed to read file model context")
|
||||
|
@ -268,7 +269,11 @@ func (handler Driver) Source(ctx context.Context, path string, ttl int64, isDown
|
|||
|
||||
finalURL := signedURI.String()
|
||||
if baseURL != nil {
|
||||
finalURL = baseURL.ResolveReference(signedURI).String()
|
||||
// 支持代理域名使用子目录
|
||||
// Support sub-directories for proxy domain
|
||||
baseURL.Path = path.Join(baseURL.Path, signedURI.Path)
|
||||
baseURL.RawQuery = signedURI.RawQuery
|
||||
finalURL = baseURL.String()
|
||||
}
|
||||
|
||||
return finalURL, nil
|
||||
|
|
|
@ -86,11 +86,11 @@ func (handler Driver) List(ctx context.Context, base string, recursive bool) ([]
|
|||
}
|
||||
|
||||
// Get 获取文件
|
||||
func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser, error) {
|
||||
func (handler Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) {
|
||||
// 获取文件源地址
|
||||
downloadURL, err := handler.Source(
|
||||
ctx,
|
||||
path,
|
||||
objectPath,
|
||||
60,
|
||||
false,
|
||||
0,
|
||||
|
@ -162,12 +162,12 @@ func (handler Driver) Thumb(ctx context.Context, file *model.File) (*response.Co
|
|||
// Source 获取外链URL
|
||||
func (handler Driver) Source(
|
||||
ctx context.Context,
|
||||
path string,
|
||||
objectPath string,
|
||||
ttl int64,
|
||||
isDownload bool,
|
||||
speed int,
|
||||
) (string, error) {
|
||||
cacheKey := fmt.Sprintf("onedrive_source_%d_%s", handler.Policy.ID, path)
|
||||
cacheKey := fmt.Sprintf("onedrive_source_%d_%s", handler.Policy.ID, objectPath)
|
||||
if file, ok := ctx.Value(fsctx.FileModelCtx).(model.File); ok {
|
||||
cacheKey = fmt.Sprintf("onedrive_source_file_%d_%d", file.UpdatedAt.Unix(), file.ID)
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ func (handler Driver) Source(
|
|||
}
|
||||
|
||||
// 缓存不存在,重新获取
|
||||
res, err := handler.Client.Meta(ctx, "", path)
|
||||
res, err := handler.Client.Meta(ctx, "", objectPath)
|
||||
if err == nil {
|
||||
// 写入新的缓存
|
||||
cache.Set(
|
||||
|
@ -206,6 +206,11 @@ func (handler Driver) replaceSourceHost(origin string) (string, error) {
|
|||
// 替换反代地址
|
||||
source.Scheme = cdn.Scheme
|
||||
source.Host = cdn.Host
|
||||
|
||||
// 支持代理域名使用子目录
|
||||
// Support sub-directories for proxy domain
|
||||
source.Path = path.Join(cdn.Path, source.Path)
|
||||
|
||||
return source.String(), nil
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ func (handler *Driver) List(ctx context.Context, base string, recursive bool) ([
|
|||
}
|
||||
|
||||
// Get 获取文件
|
||||
func (handler *Driver) Get(ctx context.Context, path string) (response.RSCloser, error) {
|
||||
func (handler *Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) {
|
||||
// 通过VersionID禁止缓存
|
||||
ctx = context.WithValue(ctx, VersionID, time.Now().UnixNano())
|
||||
|
||||
|
@ -194,7 +194,7 @@ func (handler *Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
|||
ctx = context.WithValue(ctx, fsctx.ForceUsePublicEndpointCtx, false)
|
||||
|
||||
// 获取文件源地址
|
||||
downloadURL, err := handler.Source(ctx, path, int64(model.GetIntSetting("preview_timeout", 60)), false, 0)
|
||||
downloadURL, err := handler.Source(ctx, objectPath, int64(model.GetIntSetting("preview_timeout", 60)), false, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ func (handler *Driver) Thumb(ctx context.Context, file *model.File) (*response.C
|
|||
}
|
||||
|
||||
// Source 获取外链URL
|
||||
func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDownload bool, speed int) (string, error) {
|
||||
func (handler *Driver) Source(ctx context.Context, objectPath string, ttl int64, isDownload bool, speed int) (string, error) {
|
||||
// 初始化客户端
|
||||
usePublicEndpoint := true
|
||||
if forceUsePublicEndpoint, ok := ctx.Value(fsctx.ForceUsePublicEndpointCtx).(bool); ok {
|
||||
|
@ -369,11 +369,11 @@ func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDow
|
|||
signOptions = append(signOptions, oss.TrafficLimitParam(int64(speed)))
|
||||
}
|
||||
|
||||
return handler.signSourceURL(ctx, path, ttl, signOptions)
|
||||
return handler.signSourceURL(ctx, objectPath, ttl, signOptions)
|
||||
}
|
||||
|
||||
func (handler *Driver) signSourceURL(ctx context.Context, path string, ttl int64, options []oss.Option) (string, error) {
|
||||
signedURL, err := handler.bucket.SignURL(path, oss.HTTPGet, ttl, options...)
|
||||
func (handler *Driver) signSourceURL(ctx context.Context, objectPath string, ttl int64, options []oss.Option) (string, error) {
|
||||
signedURL, err := handler.bucket.SignURL(objectPath, oss.HTTPGet, ttl, options...)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -401,6 +401,10 @@ func (handler *Driver) signSourceURL(ctx context.Context, path string, ttl int64
|
|||
}
|
||||
finalURL.Host = cdnURL.Host
|
||||
finalURL.Scheme = cdnURL.Scheme
|
||||
|
||||
// 支持代理域名使用子目录
|
||||
// Support sub-directories for proxy domain
|
||||
finalURL.Path = path.Join(cdnURL.Path, finalURL.Path)
|
||||
}
|
||||
|
||||
return finalURL.String(), nil
|
||||
|
|
|
@ -116,7 +116,7 @@ func (handler *Driver) getAPIUrl(scope string, routes ...string) string {
|
|||
}
|
||||
|
||||
// Get 获取文件内容
|
||||
func (handler *Driver) Get(ctx context.Context, path string) (response.RSCloser, error) {
|
||||
func (handler *Driver) Get(ctx context.Context, objectPath string) (response.RSCloser, error) {
|
||||
// 尝试获取速度限制
|
||||
speedLimit := 0
|
||||
if user, ok := ctx.Value(fsctx.UserCtx).(model.User); ok {
|
||||
|
@ -124,7 +124,7 @@ func (handler *Driver) Get(ctx context.Context, path string) (response.RSCloser,
|
|||
}
|
||||
|
||||
// 获取文件源地址
|
||||
downloadURL, err := handler.Source(ctx, path, 0, true, speedLimit)
|
||||
downloadURL, err := handler.Source(ctx, objectPath, 0, true, speedLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ func (handler *Driver) Thumb(ctx context.Context, file *model.File) (*response.C
|
|||
}
|
||||
|
||||
// Source 获取外链URL
|
||||
func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDownload bool, speed int) (string, error) {
|
||||
func (handler *Driver) Source(ctx context.Context, objectPath string, ttl int64, isDownload bool, speed int) (string, error) {
|
||||
// 尝试从上下文获取文件名
|
||||
fileName := "file"
|
||||
if file, ok := ctx.Value(fsctx.FileModelCtx).(model.File); ok {
|
||||
|
@ -263,7 +263,7 @@ func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDow
|
|||
}
|
||||
|
||||
// 签名下载地址
|
||||
sourcePath := base64.RawURLEncoding.EncodeToString([]byte(path))
|
||||
sourcePath := base64.RawURLEncoding.EncodeToString([]byte(objectPath))
|
||||
signedURI, err = auth.SignURI(
|
||||
handler.AuthInstance,
|
||||
fmt.Sprintf("%s/%d/%s/%s", controller, speed, sourcePath, url.PathEscape(fileName)),
|
||||
|
@ -274,9 +274,12 @@ func (handler *Driver) Source(ctx context.Context, path string, ttl int64, isDow
|
|||
return "", serializer.NewError(serializer.CodeEncryptError, "Failed to sign URL", err)
|
||||
}
|
||||
|
||||
finalURL := serverURL.ResolveReference(signedURI).String()
|
||||
return finalURL, nil
|
||||
// 支持代理域名使用子目录
|
||||
// Support sub-directories for proxy domain
|
||||
serverURL.Path = path.Join(serverURL.Path, signedURI.Path)
|
||||
serverURL.RawQuery = signedURI.RawQuery
|
||||
|
||||
return serverURL.String(), nil
|
||||
}
|
||||
|
||||
// Token 获取上传策略和认证Token
|
||||
|
|
Loading…
Add table
Reference in a new issue