Initial commit (code only without large binaries)

This commit is contained in:
robin
2026-02-15 18:58:44 +08:00
commit 35df75498f
9442 changed files with 1495866 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package ossconfigs
type OSSBucketParam = string

View File

@@ -0,0 +1,48 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package ossconfigs
type OSSBucketParam = string
const (
OSSBucketParamInput OSSBucketParam = "input" // 输入Bucket
OSSBucketParamPrefix OSSBucketParam = "prefix" // 作为前缀,类似于:/bucket/filename
OSSBucketParamArg OSSBucketParam = "arg" // 从参数中提取
OSSBucketParamSubDomain OSSBucketParam = "subDomain" // 子域名
)
type OSSBucketParamDefinition struct {
Name string `json:"name"`
Code OSSBucketParam `json:"code"`
Description string `json:"description"`
Example string `json:"example"`
}
func FindAllOSSBucketParamDefinitions() []*OSSBucketParamDefinition {
return []*OSSBucketParamDefinition{
{
Name: "指定${optionName}",
Code: OSSBucketParamInput,
Description: "在当前表单中输入${optionName}名称",
},
{
Name: "URL前缀",
Code: OSSBucketParamPrefix,
Description: "从访问的URL中的文件路径前缀中获取${optionName}名称",
Example: "/BUCKET-NAME/filename",
},
{
Name: "参数",
Code: OSSBucketParamArg,
Description: "从访问的URL参数中获取${optionName}名称",
Example: "/filename?ARG=BUCKET-NAME",
},
{
Name: "子域名",
Code: OSSBucketParamSubDomain,
Description: "从访问的子域名中获取${optionName}名称",
Example: "BUCKET-NAME.example.com/filename",
},
}
}

View File

@@ -0,0 +1,19 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package ossconfigs
type OSSConfig struct {
}
func NewOSSConfig() *OSSConfig {
return &OSSConfig{}
}
func (this *OSSConfig) Init() error {
return nil
}
func (this *OSSConfig) Summary() string {
return ""
}

View File

@@ -0,0 +1,142 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package ossconfigs
import (
"crypto/md5"
"encoding/json"
"fmt"
"net"
"net/http"
"path/filepath"
"reflect"
"strings"
)
type OSSConfig struct {
Type OSSType `yaml:"oss" json:"type"`
BucketParam OSSBucketParam `yaml:"bucketParam" json:"bucketParam"`
BucketArgName string `yaml:"bucketArgName" json:"bucketArgName"`
BucketName string `yaml:"bucketName" json:"bucketName"`
Options any `yaml:"options" json:"options"`
optionsUniqueId string
}
func NewOSSConfig() *OSSConfig {
return &OSSConfig{}
}
func (this *OSSConfig) Init() error {
if this.Options != nil {
// decode options
if reflect.TypeOf(this.Options).Kind() == reflect.Map {
optionsJSON, err := json.Marshal(this.Options)
if err != nil {
return err
}
newOptions, decodeErr := DecodeOSSOptions(this.Type, optionsJSON)
if decodeErr != nil {
return decodeErr
}
if newOptions != nil {
this.Options = newOptions
}
}
options, ok := this.Options.(OSSOptions)
if ok {
err := options.Init()
if err != nil {
return err
}
}
}
configJSON, err := json.Marshal(this)
if err != nil {
return err
}
this.optionsUniqueId = fmt.Sprintf("%x", md5.Sum(configJSON))
return nil
}
func (this *OSSConfig) Summary() string {
var def = FindOSSType(this.Type)
if def == nil {
return ""
}
var name = def.Name
switch this.BucketParam {
case OSSBucketParamInput:
if len(this.BucketName) > 0 {
return name + " - " + this.BucketName
}
case OSSBucketParamPrefix:
return name + " - /BUCKET-NAME/filename"
case OSSBucketParamArg:
return name + " - /filename?" + this.BucketArgName + "=BUCKET-NAME"
case OSSBucketParamSubDomain:
return name + " - BUCKET-NAME.HOST"
}
return name
}
func (this *OSSConfig) ParseRequest(req *http.Request, host string) (bucketName string, key string, uniqueId string) {
var def = FindOSSType(this.Type)
if def == nil {
return
}
var path = req.URL.Path
if len(path) > 0 {
path = strings.Trim(filepath.Clean(path), "/")
}
switch this.BucketParam {
case OSSBucketParamInput:
bucketName = this.BucketName
key = path
case OSSBucketParamPrefix:
var index = strings.Index(path, "/")
if index >= 0 {
bucketName = path[:index]
key = path[index+1:]
} else {
bucketName = path
key = ""
}
case OSSBucketParamArg:
bucketName = req.URL.Query().Get(this.BucketArgName)
key = path
case OSSBucketParamSubDomain:
if len(host) == 0 {
host, _, _ = net.SplitHostPort(req.URL.Host)
}
if len(host) > 0 {
var index = strings.Index(host, ".")
if index >= 0 {
bucketName = host[:index]
} else {
bucketName = host
}
}
key = path
default: // same as 'input'
bucketName = this.BucketName
key = path
}
// 需要防止外部传入无限个bucket名称造成内存泄露
if def.BucketIgnored {
bucketName = "default"
}
uniqueId = this.Type + "$" + this.optionsUniqueId + "$" + bucketName
key = strings.TrimLeft(strings.TrimSpace(key), "/")
return
}

View File

@@ -0,0 +1,7 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package ossconfigs
type OSSOptions interface {
Init() error // 初始化
}

View File

@@ -0,0 +1,32 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package ossconfigs
import "errors"
type OSSType = string
type OSSTypeDefinition struct {
Name string `json:"name"`
Code string `json:"code"`
BucketOptionName string `json:"bucketOptionName"`
BucketIgnored bool `json:"bucketIgnored"` // 是否忽略Bucket名称
}
func FindAllOSSTypes() []*OSSTypeDefinition {
return []*OSSTypeDefinition{}
}
func FindOSSType(code string) *OSSTypeDefinition {
for _, t := range FindAllOSSTypes() {
if t.Code == code {
return t
}
}
return nil
}
func DecodeOSSOptions(ossType OSSType, optionsJSON []byte) (any, error) {
return nil, errors.New("'" + ossType + "' has not been supported")
}

View File

@@ -0,0 +1,116 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package ossconfigs
import (
"encoding/json"
"errors"
)
type OSSType = string
// 为了方便识别每个代号前面都增加oss:标记
const (
OSSTypeTencentCOS OSSType = "oss:tencentCOS"
OSSTypeAliyunOSS OSSType = "oss:aliyunOSS"
OSSTypeHuaweiOBS OSSType = "oss:huaweiOBS"
OSSTypeBaiduBOS OSSType = "oss:baiduBOS"
OSSTypeQiniuKodo OSSType = "oss:qiniuKodo"
OSSTypeAmazonS3 OSSType = "oss:amazonS3"
OSSTypeB2 OSSType = "oss:b2"
)
type OSSTypeDefinition struct {
Name string `json:"name"`
Code string `json:"code"`
BucketOptionName string `json:"bucketOptionName"`
BucketIgnored bool `json:"bucketIgnored"` // 是否忽略Bucket名称
}
func FindAllOSSTypes() []*OSSTypeDefinition {
return []*OSSTypeDefinition{
{
Name: "腾讯云COS",
Code: OSSTypeTencentCOS,
BucketOptionName: "存储桶",
},
{
Name: "阿里云OSS",
Code: OSSTypeAliyunOSS,
BucketOptionName: "存储空间",
},
{
Name: "华为云OBS",
Code: OSSTypeHuaweiOBS,
BucketOptionName: "存储桶",
},
{
Name: "百度云BOS",
Code: OSSTypeBaiduBOS,
BucketOptionName: "Bucket",
},
{
Name: "七牛云Kodo",
Code: OSSTypeQiniuKodo,
BucketOptionName: "存储空间",
BucketIgnored: true,
},
{
Name: "Amazon S3",
Code: OSSTypeAmazonS3,
BucketOptionName: "存储桶",
},
{
Name: "B2云存储",
Code: OSSTypeB2,
BucketOptionName: "存储桶",
},
}
}
func FindOSSType(code string) *OSSTypeDefinition {
for _, t := range FindAllOSSTypes() {
if t.Code == code {
return t
}
}
return nil
}
func DecodeOSSOptions(ossType OSSType, optionsJSON []byte) (any, error) {
if len(optionsJSON) == 0 {
return nil, errors.New("invalid 'optionsJSON' for '" + ossType + "': should not be empty")
}
var ptr any
switch ossType {
case OSSTypeTencentCOS:
ptr = NewTencentCOSProviderOptions()
case OSSTypeAliyunOSS:
ptr = NewAliyunOSSProviderOptions()
case OSSTypeHuaweiOBS:
ptr = NewHuaweiOBSProviderOptions()
case OSSTypeBaiduBOS:
ptr = NewBaiduBOSProviderOptions()
case OSSTypeQiniuKodo:
ptr = NewQiniuKodoProviderOptions()
case OSSTypeAmazonS3:
ptr = NewAmazonS3ProviderOptions()
case OSSTypeB2:
ptr = NewAmazonS3ProviderOptions() // 使用S3协议
default:
return nil, errors.New("oss type '" + ossType + "' has not been supported")
}
if ptr != nil {
err := json.Unmarshal(optionsJSON, ptr)
if err != nil {
return nil, err
}
return ptr, nil
}
return nil, errors.New("could not decode 'optionsJSON': 'ptr' should not be nil")
}

View File

@@ -0,0 +1,9 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package ossconfigs
import "strings"
func IsOSSProtocol(protocol string) bool {
return strings.HasPrefix(protocol, "oss:")
}

View File

@@ -0,0 +1,19 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package ossconfigs
// AliyunOSSProviderOptions 阿里云OSS选项
type AliyunOSSProviderOptions struct {
Endpoint string `yaml:"endpoint" json:"endpoint"` // 地域节点
AccessKeyId string `yaml:"accessKeyId" json:"accessKeyId"` // AccessKey ID
AccessKeySecret string `yaml:"accessKeySecret" json:"accessKeySecret"` // AccessKey Secret
}
func NewAliyunOSSProviderOptions() *AliyunOSSProviderOptions {
return &AliyunOSSProviderOptions{}
}
func (this *AliyunOSSProviderOptions) Init() error {
return nil
}

View File

@@ -0,0 +1,29 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package ossconfigs
type AmazonS3BucketAddressStyle = string
const (
AmazonS3BucketAddressStylePath AmazonS3BucketAddressStyle = "path"
AmazonS3BucketAddressStyleDomain AmazonS3BucketAddressStyle = "domain"
)
type AmazonS3ProviderOptions struct {
AccessKeyId string `yaml:"accessKeyId" json:"accessKeyId"` // Access key ID (AK)
AccessKeySecret string `yaml:"accessKeySecret" json:"accessKeySecret"` // Secret Access Key (SK)
Region string `yaml:"region" json:"region"` // AWS Region
Endpoint string `yaml:"endpoint" json:"endpoint"` // Endpoint
BucketAddressStyle AmazonS3BucketAddressStyle `yaml:"bucketAddressStyle" json:"bucketAddressStyle"` // Bucket address style
}
func NewAmazonS3ProviderOptions() *AmazonS3ProviderOptions {
return &AmazonS3ProviderOptions{
BucketAddressStyle: AmazonS3BucketAddressStylePath,
}
}
func (this *AmazonS3ProviderOptions) Init() error {
return nil
}

View File

@@ -0,0 +1,17 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package ossconfigs
type BaiduBOSProviderOptions struct {
AccessKey string `yaml:"accessKey" json:"accessKey"`
SecretKey string `yaml:"secretKey" json:"secretKey"`
Endpoint string `yaml:"endpoint" json:"endpoint"` // https://cloud.baidu.com/doc/BOS/s/akrqd2wcx
}
func NewBaiduBOSProviderOptions() *BaiduBOSProviderOptions {
return &BaiduBOSProviderOptions{}
}
func (this *BaiduBOSProviderOptions) Init() error {
return nil
}

View File

@@ -0,0 +1,19 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package ossconfigs
// HuaweiOBSProviderOptions 华为OBS选项
type HuaweiOBSProviderOptions struct {
AccessKeyId string `yaml:"accessKeyId" json:"accessKeyId"` // 访问密钥ID
AccessKeySecret string `yaml:"accessKeySecret" json:"accessKeySecret"` // 访问密钥Secret
Endpoint string `yaml:"endpoint" json:"endpoint"` // 区域Endpoint
}
func NewHuaweiOBSProviderOptions() *HuaweiOBSProviderOptions {
return &HuaweiOBSProviderOptions{}
}
func (this *HuaweiOBSProviderOptions) Init() error {
return nil
}

View File

@@ -0,0 +1,20 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package ossconfigs
type QiniuKodoProviderOptions struct {
AccessKey string `yaml:"accessKey" json:"accessKey"` // AccessKey
SecretKey string `yaml:"secretKey" json:"secretKey"` // SecretKey
IsPublic bool `yaml:"isPublic" json:"isPublic"` // 是否为公开
Protocol string `yaml:"protocol" json:"protocol"` // 访问协议http|https
Domain string `yaml:"domain" json:"domain"` // 访问域名
}
func NewQiniuKodoProviderOptions() *QiniuKodoProviderOptions {
return &QiniuKodoProviderOptions{}
}
func (this *QiniuKodoProviderOptions) Init() error {
return nil
}

View File

@@ -0,0 +1,19 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package ossconfigs
// TencentCOSProviderOptions 腾讯COS选项
type TencentCOSProviderOptions struct {
SecretId string `yaml:"secretId" json:"secretId"` // 密钥ID
SecretKey string `yaml:"secretKey" json:"secretKey"` // 密钥Key
Region string `yaml:"region" json:"region"` // 所属区域
}
func NewTencentCOSProviderOptions() *TencentCOSProviderOptions {
return &TencentCOSProviderOptions{}
}
func (this *TencentCOSProviderOptions) Init() error {
return nil
}