// 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 }