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"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tickstep/aliyunpan/internal/utils"
|
||||||
"github.com/tickstep/library-go/logger"
|
"github.com/tickstep/library-go/logger"
|
||||||
"github.com/tickstep/library-go/requester"
|
"github.com/tickstep/library-go/requester"
|
||||||
)
|
)
|
||||||
@@ -103,31 +104,15 @@ func fixCacheSize(size *int) {
|
|||||||
|
|
||||||
// IsUrlExpired 下载链接是否已过期。过期返回True
|
// IsUrlExpired 下载链接是否已过期。过期返回True
|
||||||
func IsUrlExpired(urlStr string) bool {
|
func IsUrlExpired(urlStr string) bool {
|
||||||
u, err := url.Parse(urlStr)
|
expiredTimeSec, err := utils.GetExpiredTimeSecFromOSSUrl(urlStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// 解析错误,默认过期
|
||||||
return true
|
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秒钟
|
if (expiredTimeSec - time.Now().Unix()) <= 5 { // 小于5秒钟
|
||||||
// expired
|
// expired
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// 返回未过期
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,15 +16,15 @@ package panupload
|
|||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"github.com/tickstep/aliyunpan/internal/config"
|
|
||||||
"github.com/tickstep/library-go/converter"
|
|
||||||
"github.com/tickstep/library-go/logger"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"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 (
|
const (
|
||||||
@@ -55,16 +55,16 @@ func getBlockSize(fileSize int64) int64 {
|
|||||||
|
|
||||||
// IsUrlExpired 上传链接是否已过期。过期返回True
|
// IsUrlExpired 上传链接是否已过期。过期返回True
|
||||||
func IsUrlExpired(urlStr string) bool {
|
func IsUrlExpired(urlStr string) bool {
|
||||||
u, err := url.Parse(urlStr)
|
expiredTimeSec, err := utils.GetExpiredTimeSecFromOSSUrl(urlStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// 解析错误,默认过期
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
expiredTimeSecStr := u.Query().Get("x-oss-expires")
|
|
||||||
expiredTimeSec, _ := strconv.ParseInt(expiredTimeSecStr, 10, 64)
|
|
||||||
if (expiredTimeSec - time.Now().Unix()) <= 300 { // 小于5分钟
|
if (expiredTimeSec - time.Now().Unix()) <= 300 { // 小于5分钟
|
||||||
// expired
|
// expired
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// 返回未过期
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -383,3 +383,64 @@ func GetPublicIP() (string, error) {
|
|||||||
ip := strings.TrimSpace(strings.Split(ipResp.Origin, ",")[0])
|
ip := strings.TrimSpace(strings.Split(ipResp.Origin, ",")[0])
|
||||||
return ip, nil
|
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