feat: load oss media config from sys config
This commit is contained in:
@@ -131,6 +131,10 @@ func (oh *ossHandler) loadSysConfig() error {
|
||||
"oss_access_key_id",
|
||||
"oss_access_key_secret",
|
||||
"oss_presign_ttl",
|
||||
"oss_serve_url",
|
||||
"oss_cache_control",
|
||||
"oss_cors_origins",
|
||||
"oss_verify_bucket",
|
||||
)
|
||||
if err != nil {
|
||||
return errors.New("failed to load OSS config from sys config: " + err.Error())
|
||||
@@ -146,6 +150,14 @@ func (oh *ossHandler) loadSysConfig() error {
|
||||
applyString(&oh.conf.RegionID, values["oss_region_id"])
|
||||
applyString(&oh.conf.AccessKeyID, values["oss_access_key_id"])
|
||||
applyString(&oh.conf.AccessKeySecret, values["oss_access_key_secret"])
|
||||
applyString(&oh.conf.ServeURL, values["oss_serve_url"])
|
||||
applyString(&oh.conf.CacheControl, values["oss_cache_control"])
|
||||
if origins := parseStringList(values["oss_cors_origins"]); len(origins) > 0 {
|
||||
oh.conf.CorsOrigins = origins
|
||||
}
|
||||
if verify := strings.TrimSpace(values["oss_verify_bucket"]); verify != "" {
|
||||
oh.conf.VerifyBucket = truthy(verify)
|
||||
}
|
||||
if ttl := strings.TrimSpace(values["oss_presign_ttl"]); ttl != "" {
|
||||
parsed, err := strconv.Atoi(ttl)
|
||||
if err != nil {
|
||||
@@ -156,6 +168,30 @@ func (oh *ossHandler) loadSysConfig() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseStringList(value string) []string {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
return nil
|
||||
}
|
||||
var items []string
|
||||
if strings.HasPrefix(value, "[") {
|
||||
if err := json.Unmarshal([]byte(value), &items); err == nil {
|
||||
return compactStrings(items)
|
||||
}
|
||||
}
|
||||
return compactStrings(strings.Split(value, ","))
|
||||
}
|
||||
|
||||
func compactStrings(values []string) []string {
|
||||
items := make([]string, 0, len(values))
|
||||
for _, value := range values {
|
||||
if value = strings.TrimSpace(value); value != "" {
|
||||
items = append(items, value)
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func applyString(target *string, value string) {
|
||||
if value = strings.TrimSpace(value); value != "" {
|
||||
*target = value
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package oss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
aliyunoss "github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
"github.com/tinode/chat/server/media"
|
||||
)
|
||||
|
||||
func TestLiveAliyunOSSUploadPublic(t *testing.T) {
|
||||
endpoint := os.Getenv("LIVE_OSS_ENDPOINT")
|
||||
bucket := os.Getenv("LIVE_OSS_BUCKET")
|
||||
accessKeyID := os.Getenv("LIVE_OSS_ACCESS_KEY_ID")
|
||||
accessKeySecret := os.Getenv("LIVE_OSS_ACCESS_KEY_SECRET")
|
||||
if endpoint == "" || bucket == "" || accessKeyID == "" || accessKeySecret == "" {
|
||||
t.Skip("LIVE_OSS_* env is not configured")
|
||||
}
|
||||
|
||||
conf, err := json.Marshal(ossConfig{
|
||||
Endpoint: endpoint,
|
||||
BucketName: bucket,
|
||||
AccessKeyID: accessKeyID,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
PresignTTL: 60,
|
||||
CacheControl: "no-cache",
|
||||
CorsOrigins: []string{"*"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handler := &ossHandler{}
|
||||
if err = handler.Init(string(conf)); err != nil {
|
||||
t.Fatalf("oss init failed: %v", err)
|
||||
}
|
||||
|
||||
body := []byte{0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n'}
|
||||
file := &media.PublicFileDef{
|
||||
ID: "codex-live-" + time.Now().UTC().Format("20060102150405"),
|
||||
Purpose: "codex_live",
|
||||
MimeType: "image/png",
|
||||
CreatedAt: time.Now().UTC(),
|
||||
}
|
||||
location, size, err := handler.UploadPublic(file, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
t.Fatalf("oss upload failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := handler.Delete([]string{file.Location}); err != nil {
|
||||
t.Logf("oss cleanup failed: %v", err)
|
||||
}
|
||||
}()
|
||||
if size != int64(len(body)) || location == "" || file.Location == "" || file.ETag == "" {
|
||||
t.Fatalf("unexpected upload result: location=%q file=%+v size=%d", location, file, size)
|
||||
}
|
||||
|
||||
got, err := handler.bucket.GetObject(file.Location)
|
||||
if err != nil {
|
||||
t.Fatalf("oss get object failed: %v", err)
|
||||
}
|
||||
defer got.Close()
|
||||
downloaded, err := io.ReadAll(got)
|
||||
if err != nil {
|
||||
t.Fatalf("oss read object failed: %v", err)
|
||||
}
|
||||
if !bytes.Equal(downloaded, body) {
|
||||
t.Fatalf("oss downloaded bytes mismatch: got %x want %x", downloaded, body)
|
||||
}
|
||||
|
||||
signedURL, err := handler.bucket.SignURL(file.Location, aliyunoss.HTTPGet, 60)
|
||||
if err != nil {
|
||||
t.Fatalf("oss sign url failed: %v", err)
|
||||
}
|
||||
resp, err := http.Get(signedURL)
|
||||
if err != nil {
|
||||
t.Fatalf("oss signed url get failed: %v", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
t.Fatalf("oss signed url get status=%d", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,10 @@ func TestLoadSysConfig(t *testing.T) {
|
||||
"oss_access_key_id": "ak",
|
||||
"oss_access_key_secret": "sk",
|
||||
"oss_presign_ttl": "300",
|
||||
"oss_serve_url": "/files/",
|
||||
"oss_cache_control": "private",
|
||||
"oss_cors_origins": `["https://example.com"]`,
|
||||
"oss_verify_bucket": "true",
|
||||
}
|
||||
defer func() { store.ThirdPartyConfig = original }()
|
||||
|
||||
@@ -70,4 +74,10 @@ func TestLoadSysConfig(t *testing.T) {
|
||||
if handler.conf.RegionID != "cn-shenzhen" || handler.conf.PresignTTL != 300 {
|
||||
t.Fatalf("unexpected OSS region or ttl: %+v", handler.conf)
|
||||
}
|
||||
if handler.conf.ServeURL != "/files/" || handler.conf.CacheControl != "private" || !handler.conf.VerifyBucket {
|
||||
t.Fatalf("unexpected OSS serve settings: %+v", handler.conf)
|
||||
}
|
||||
if len(handler.conf.CorsOrigins) != 1 || handler.conf.CorsOrigins[0] != "https://example.com" {
|
||||
t.Fatalf("unexpected OSS cors origins: %+v", handler.conf.CorsOrigins)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user