155 lines
3.5 KiB
Go
155 lines
3.5 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/huaweicloud/huaweicloud-sdk-go-obs/obs"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
type HuaweiOBSProvider struct {
|
|
buckerName string
|
|
client *obs.ObsClient
|
|
}
|
|
|
|
func NewHuaweiOBSProvider() *HuaweiOBSProvider {
|
|
return &HuaweiOBSProvider{}
|
|
}
|
|
|
|
func (this *HuaweiOBSProvider) Init(options ossconfigs.OSSOptions, bucketName string) error {
|
|
realOptions, ok := options.(*ossconfigs.HuaweiOBSProviderOptions)
|
|
if !ok {
|
|
return errors.New("invalid options for 'HuaweiOBSProvider'")
|
|
}
|
|
|
|
this.buckerName = bucketName
|
|
|
|
client, err := obs.New(realOptions.AccessKeyId, realOptions.AccessKeySecret, "https://"+realOptions.Endpoint)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
this.client = client
|
|
|
|
return nil
|
|
}
|
|
|
|
func (this *HuaweiOBSProvider) Head(key string) (httpResponse *http.Response, nativeErrCode string, err error) {
|
|
var input = &obs.HeadObjectInput{
|
|
Bucket: this.buckerName,
|
|
Key: key,
|
|
}
|
|
output, respErr := this.client.HeadObject(input)
|
|
if respErr != nil {
|
|
nativeErrCode, err = this.parseErr(respErr)
|
|
return
|
|
}
|
|
|
|
httpResponse = &http.Response{
|
|
StatusCode: output.StatusCode,
|
|
ContentLength: 0,
|
|
Header: this.formatHeaders(output.ResponseHeaders),
|
|
Body: io.NopCloser(bytes.NewReader(nil)),
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *HuaweiOBSProvider) Get(key string) (httpResponse *http.Response, nativeErrCode string, err error) {
|
|
var input = &obs.GetObjectInput{}
|
|
input.Bucket = this.buckerName
|
|
input.Key = key
|
|
output, respErr := this.client.GetObject(input)
|
|
if respErr != nil {
|
|
nativeErrCode, err = this.parseErr(respErr)
|
|
return
|
|
}
|
|
|
|
httpResponse = &http.Response{
|
|
StatusCode: output.StatusCode,
|
|
ContentLength: output.ContentLength,
|
|
Header: this.formatHeaders(output.ResponseHeaders),
|
|
Body: output.Body,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *HuaweiOBSProvider) 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)
|
|
}
|
|
|
|
var input = &obs.GetObjectInput{}
|
|
input.Bucket = this.buckerName
|
|
input.Key = key
|
|
input.RangeStart = start
|
|
input.RangeEnd = end
|
|
output, respErr := this.client.GetObject(input)
|
|
if respErr != nil {
|
|
nativeErrCode, err = this.parseErr(respErr)
|
|
return
|
|
}
|
|
|
|
httpResponse = &http.Response{
|
|
StatusCode: output.StatusCode,
|
|
ContentLength: output.ContentLength,
|
|
Header: this.formatHeaders(output.ResponseHeaders),
|
|
Body: output.Body,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *HuaweiOBSProvider) parseErr(err error) (errCode string, resultErr error) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
resultErr = err
|
|
|
|
respErr, ok := err.(obs.ObsError)
|
|
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 *HuaweiOBSProvider) formatHeaders(rawHeader http.Header) (resultHeader http.Header) {
|
|
resultHeader = http.Header{}
|
|
for k, v := range rawHeader {
|
|
if k == "x-reserved" {
|
|
continue
|
|
}
|
|
|
|
resultHeader[http.CanonicalHeaderKey(k)] = v
|
|
}
|
|
return resultHeader
|
|
}
|