Files
waf-platform/EdgeNode/internal/oss/provider_huawei_obs.go
2026-02-04 20:27:13 +08:00

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
}