You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
2.8 KiB
127 lines
2.8 KiB
5 months ago
|
package v1
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"net/url"
|
||
|
"regexp"
|
||
|
"strings"
|
||
|
|
||
|
"gitea.drugeyes.vip/pharnexbase/utils/pkg/set"
|
||
|
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||
|
"github.com/go-kratos/kratos/v2/middleware"
|
||
|
"github.com/go-kratos/kratos/v2/transport"
|
||
|
)
|
||
|
|
||
|
type Signer struct {
|
||
|
client *oss.Client
|
||
|
bucketsWl []string
|
||
|
expiredInSec int64 // 默认 7 天有效期
|
||
|
}
|
||
|
|
||
|
func NewSigner(client *oss.Client) *Signer {
|
||
|
return &Signer{
|
||
|
client: client,
|
||
|
expiredInSec: 604800,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type UrlInfo struct {
|
||
|
Bucket string
|
||
|
Endpoint string
|
||
|
Object string
|
||
|
FileName string
|
||
|
}
|
||
|
|
||
|
func (s *Signer) SetBucketsWhiteList(bucketsWl []string) *Signer {
|
||
|
s.bucketsWl = bucketsWl
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
func (s *Signer) SetExpiredInSec(expiredInSec int64) *Signer {
|
||
|
s.expiredInSec = expiredInSec
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
func (s *Signer) SignUrl() middleware.Middleware {
|
||
|
return func(handler middleware.Handler) middleware.Handler {
|
||
|
return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
|
||
|
reply, err = handler(ctx, req)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if _, ok := transport.FromServerContext(ctx); ok {
|
||
|
// 后置匹配 oss 地址,签名 url,替换输出
|
||
|
var marshal []byte
|
||
|
marshal, err = json.Marshal(reply)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
jsonStr := string(marshal)
|
||
|
|
||
|
r := regexp.MustCompile("\"(https?://[-.a-z0-9]+\\.aliyuncs\\.com/[^\"\\\\]+)\\\\*\"")
|
||
|
res := r.FindAllStringSubmatch(jsonStr, -1)
|
||
|
for _, mu := range res {
|
||
|
urlInfo, ue := GetUrlInfo(mu[1]) // url错误则不处理,用户中心不处理
|
||
|
if ue == nil && !set.NewSetWithItems(s.bucketsWl...).Has(urlInfo.Bucket){
|
||
|
var bucket *oss.Bucket
|
||
|
bucket, err = s.client.Bucket(urlInfo.Bucket)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 生成用于下载的签名URL,并指定签名URL的有效时间。
|
||
|
var surl string
|
||
|
surl, err = bucket.SignURL(urlInfo.Object, oss.HTTPGet, s.expiredInSec)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 使用签名url替换原始url
|
||
|
jsonStr = strings.Replace(jsonStr, mu[1], surl, -1)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 覆盖原始输出
|
||
|
err = json.Unmarshal([]byte(jsonStr), reply)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func GetUrlInfo(ossUrl string) (*UrlInfo, error) {
|
||
|
parse, err := url.Parse(ossUrl)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
hostInfo := strings.SplitN(parse.Host, ".", 2)
|
||
|
if len(hostInfo) != 2 {
|
||
|
return nil, errors.New("oss url error")
|
||
|
}
|
||
|
|
||
|
object := strings.TrimLeft(parse.Path, "/")
|
||
|
if object == "" {
|
||
|
return nil, errors.New("oss url error")
|
||
|
}
|
||
|
|
||
|
objectInfo := strings.Split(object, "/")
|
||
|
if len(object) == 0 {
|
||
|
return nil, errors.New("oss url error")
|
||
|
}
|
||
|
fileName := objectInfo[len(objectInfo)-1]
|
||
|
|
||
|
return &UrlInfo{
|
||
|
Bucket: hostInfo[0],
|
||
|
Endpoint: hostInfo[1],
|
||
|
Object: object,
|
||
|
FileName: fileName,
|
||
|
}, err
|
||
|
}
|