182 lines
4.4 KiB
Go
182 lines
4.4 KiB
Go
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
|
//go:build plus
|
|
|
|
package oss
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ossconfigs"
|
|
"github.com/baidubce/bce-sdk-go/bce"
|
|
"github.com/baidubce/bce-sdk-go/services/bos"
|
|
"github.com/baidubce/bce-sdk-go/services/bos/api"
|
|
"github.com/iwind/TeaGo/types"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
type BaiduBOSProvider struct {
|
|
bucketName string
|
|
client *bos.Client
|
|
}
|
|
|
|
func NewBaiduBOSProvider() *BaiduBOSProvider {
|
|
return &BaiduBOSProvider{}
|
|
}
|
|
|
|
func (this *BaiduBOSProvider) Init(options ossconfigs.OSSOptions, bucketName string) error {
|
|
realOptions, ok := options.(*ossconfigs.BaiduBOSProviderOptions)
|
|
if !ok {
|
|
return errors.New("invalid options for 'BaiduOBSProvider'")
|
|
}
|
|
|
|
this.bucketName = bucketName
|
|
|
|
client, err := bos.NewClient(realOptions.AccessKey, realOptions.SecretKey, "https://"+realOptions.Endpoint)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
this.client = client
|
|
|
|
return nil
|
|
}
|
|
|
|
func (this *BaiduBOSProvider) Head(key string) (httpResponse *http.Response, nativeErrCode string, err error) {
|
|
result, respErr := this.client.GetObjectMeta(this.bucketName, key)
|
|
if respErr != nil {
|
|
nativeErrCode, err = this.parseErr(respErr)
|
|
return
|
|
}
|
|
|
|
httpResponse = &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Header: this.composeHeader(result.ObjectMeta),
|
|
ContentLength: result.ContentLength,
|
|
Body: io.NopCloser(bytes.NewReader(nil)),
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (this *BaiduBOSProvider) Get(key string) (httpResponse *http.Response, nativeErrCode string, err error) {
|
|
result, respErr := this.client.BasicGetObject(this.bucketName, key)
|
|
if respErr != nil {
|
|
nativeErrCode, err = this.parseErr(respErr)
|
|
return
|
|
}
|
|
|
|
httpResponse = &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Header: this.composeHeader(result.ObjectMeta),
|
|
ContentLength: result.ContentLength,
|
|
Body: result.Body,
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (this *BaiduBOSProvider) GetRange(key string, bytesRange string) (httpResponse *http.Response, nativeErrCode string, err error) {
|
|
rangeResult, parseOk := httpRequestParseRangeHeader(bytesRange)
|
|
if !parseOk || len(rangeResult) == 0 {
|
|
return this.Get(key)
|
|
}
|
|
|
|
var firstRange = rangeResult[0]
|
|
var start = firstRange.Start()
|
|
var end = firstRange.End()
|
|
if start < 0 || end < 0 || start > end {
|
|
return this.Get(key)
|
|
}
|
|
|
|
result, respErr := this.client.GetObject(this.bucketName, key, nil, start, end)
|
|
if respErr != nil {
|
|
nativeErrCode, err = this.parseErr(respErr)
|
|
return
|
|
}
|
|
|
|
var statusCode = http.StatusOK
|
|
if len(result.ContentRange) > 0 {
|
|
statusCode = http.StatusPartialContent
|
|
}
|
|
|
|
httpResponse = &http.Response{
|
|
StatusCode: statusCode,
|
|
Header: this.composeHeader(result.ObjectMeta),
|
|
ContentLength: result.ContentLength,
|
|
Body: result.Body,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *BaiduBOSProvider) parseErr(err error) (errCode string, resultErr error) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
resultErr = err
|
|
|
|
respErr, ok := err.(*bce.BceServiceError)
|
|
if ok {
|
|
errCode = respErr.Code
|
|
}
|
|
|
|
// 特殊错误
|
|
if errCode == "NoSuchBucket" {
|
|
resultErr = errNoBucket
|
|
return
|
|
}
|
|
|
|
if errCode == "NoSuchKey" {
|
|
resultErr = errNotFound
|
|
return
|
|
}
|
|
|
|
if errCode == "RequestTimeout" {
|
|
resultErr = errRequestTimeout
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (this *BaiduBOSProvider) composeHeader(result api.ObjectMeta) http.Header {
|
|
var header = http.Header{}
|
|
|
|
if len(result.CacheControl) > 0 {
|
|
header.Set("Cache-Control", result.CacheControl)
|
|
}
|
|
if len(result.ContentDisposition) > 0 {
|
|
header.Set("Content-Disposition", result.ContentDisposition)
|
|
}
|
|
if len(result.ContentEncoding) > 0 {
|
|
header.Set("Content-Encoding", result.ContentEncoding)
|
|
}
|
|
header.Set("Content-Length", types.String(result.ContentLength))
|
|
if len(result.ContentRange) > 0 {
|
|
header.Set("Content-Range", result.ContentRange)
|
|
}
|
|
if len(result.ContentType) > 0 {
|
|
header.Set("Content-Type", result.ContentType)
|
|
}
|
|
if len(result.ContentMD5) > 0 {
|
|
header["Content-MD5"] = []string{result.ContentMD5}
|
|
}
|
|
if len(result.ContentSha256) > 0 {
|
|
header.Set("Content-Sha256", result.ContentSha256)
|
|
}
|
|
if len(result.ContentCrc32) > 0 {
|
|
header.Set("Content-Crc32", result.ContentCrc32)
|
|
}
|
|
if len(result.Expires) > 0 {
|
|
header.Set("Expires", result.Expires)
|
|
}
|
|
if len(result.LastModified) > 0 {
|
|
header.Set("Last-Modified", result.LastModified)
|
|
}
|
|
if len(result.ETag) > 0 {
|
|
header["ETag"] = []string{result.ETag}
|
|
}
|
|
|
|
return header
|
|
}
|