mirror of
https://gitee.com/zhangsken/aliyunpan.git
synced 2026-10-16 02:23:49 +08:00
refractor OSS url parser
This commit is contained in:
@@ -23,6 +23,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/tickstep/aliyunpan/internal/utils"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
"github.com/tickstep/library-go/requester"
|
||||
)
|
||||
@@ -103,31 +104,15 @@ func fixCacheSize(size *int) {
|
||||
|
||||
// IsUrlExpired 下载链接是否已过期。过期返回True
|
||||
func IsUrlExpired(urlStr string) bool {
|
||||
u, err := url.Parse(urlStr)
|
||||
expiredTimeSec, err := utils.GetExpiredTimeSecFromOSSUrl(urlStr)
|
||||
if err != nil {
|
||||
// 解析错误,默认过期
|
||||
return true
|
||||
}
|
||||
// OSS V4签名:x-oss-date=20260629T010316Z&x-oss-expires=900
|
||||
expiredDateStr := u.Query().Get("x-oss-date") // 该请求/签名生成的时间
|
||||
expiredTimeSecStr := u.Query().Get("x-oss-expires") // Presigned URL 的过期时间(单位:秒)
|
||||
|
||||
// 解析 x-oss-date(ISO8601,UTC)
|
||||
expiredDate, err := time.Parse("20060102T150405Z", expiredDateStr)
|
||||
if err != nil {
|
||||
// 非法时间格式
|
||||
return true
|
||||
}
|
||||
// 解析 x-oss-expires(秒)
|
||||
expireSec, err := strconv.ParseInt(expiredTimeSecStr, 10, 64)
|
||||
if err != nil || expireSec <= 0 {
|
||||
// 非法过期时间
|
||||
return true
|
||||
}
|
||||
// 计算过期时间戳(Unix seconds)
|
||||
expiredTimeSec := expiredDate.Unix() + expireSec
|
||||
if (expiredTimeSec - time.Now().Unix()) <= 5 { // 小于5秒钟
|
||||
// expired
|
||||
return true
|
||||
}
|
||||
// 返回未过期
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@ package panupload
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"github.com/tickstep/aliyunpan/internal/config"
|
||||
"github.com/tickstep/library-go/converter"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tickstep/aliyunpan/internal/config"
|
||||
"github.com/tickstep/aliyunpan/internal/utils"
|
||||
"github.com/tickstep/library-go/converter"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -55,16 +55,16 @@ func getBlockSize(fileSize int64) int64 {
|
||||
|
||||
// IsUrlExpired 上传链接是否已过期。过期返回True
|
||||
func IsUrlExpired(urlStr string) bool {
|
||||
u, err := url.Parse(urlStr)
|
||||
expiredTimeSec, err := utils.GetExpiredTimeSecFromOSSUrl(urlStr)
|
||||
if err != nil {
|
||||
// 解析错误,默认过期
|
||||
return true
|
||||
}
|
||||
expiredTimeSecStr := u.Query().Get("x-oss-expires")
|
||||
expiredTimeSec, _ := strconv.ParseInt(expiredTimeSecStr, 10, 64)
|
||||
if (expiredTimeSec - time.Now().Unix()) <= 300 { // 小于5分钟
|
||||
// expired
|
||||
return true
|
||||
}
|
||||
// 返回未过期
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -383,3 +383,64 @@ func GetPublicIP() (string, error) {
|
||||
ip := strings.TrimSpace(strings.Split(ipResp.Origin, ",")[0])
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// GetExpiredTimeSecFromOSSUrl 从OSS URL中解析出统一的过期时间戳(秒)
|
||||
func GetExpiredTimeSecFromOSSUrl(rawURL string) (int64, error) {
|
||||
parsedURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to parse URL: %w", err)
|
||||
}
|
||||
|
||||
query := parsedURL.Query()
|
||||
sigVersion := query.Get("x-oss-signature-version")
|
||||
|
||||
var expires int64 = 0
|
||||
|
||||
// 检测版本标识(不区分大小写)
|
||||
if strings.Contains(sigVersion, "OSS4") {
|
||||
// V4 签名:x-oss-expires 为相对秒数,需要结合 x-oss-date
|
||||
expiresStr := query.Get("x-oss-expires")
|
||||
if expiresStr == "" {
|
||||
return 0, fmt.Errorf("V4 signature: 'x-oss-expires' parameter not found")
|
||||
}
|
||||
relSec, err := strconv.ParseInt(expiresStr, 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("V4 signature: invalid 'x-oss-expires' value: %w", err)
|
||||
}
|
||||
|
||||
dateStr := query.Get("x-oss-date")
|
||||
if dateStr == "" {
|
||||
return 0, fmt.Errorf("V4 signature: 'x-oss-date' parameter not found")
|
||||
}
|
||||
// 解析 ISO8601 UTC 时间,例如 "20231220T083018Z"
|
||||
t, err := time.Parse("20060102T150405Z", dateStr)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("V4 signature: failed to parse 'x-oss-date': %w", err)
|
||||
}
|
||||
expires = t.Unix() + relSec
|
||||
|
||||
} else if strings.Contains(sigVersion, "OSS3") || strings.Contains(sigVersion, "OSS2") {
|
||||
// V2 / V3:x-oss-expires 为绝对时间戳
|
||||
expiresStr := query.Get("x-oss-expires")
|
||||
if expiresStr == "" {
|
||||
return 0, fmt.Errorf("V2/V3 signature: 'x-oss-expires' parameter not found")
|
||||
}
|
||||
expires, err = strconv.ParseInt(expiresStr, 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("V2/V3 signature: invalid 'x-oss-expires' value: %w", err)
|
||||
}
|
||||
|
||||
} else {
|
||||
// 默认为 V1 签名(没有 x-oss-signature-version 或为空)
|
||||
expiresStr := query.Get("Expires")
|
||||
if expiresStr == "" {
|
||||
return 0, fmt.Errorf("V1 signature: 'Expires' parameter not found")
|
||||
}
|
||||
expires, err = strconv.ParseInt(expiresStr, 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("V1 signature: invalid 'Expires' value: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return expires, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user