Files
opencloud/services/search/pkg/content/cs3.go
2025-01-21 11:16:38 +01:00

88 lines
2.3 KiB
Go

package content
import (
"context"
"crypto/tls"
"fmt"
"io"
"net/http"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/opencloud-eu/opencloud/pkg/log"
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
)
type cs3 struct {
httpClient http.Client
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
logger log.Logger
}
func newCS3Retriever(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], logger log.Logger, insecure bool) cs3 {
return cs3{
httpClient: http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure}, //nolint:gosec
},
},
gatewaySelector: gatewaySelector,
logger: logger,
}
}
// Retrieve downloads the file from a cs3 service
// The caller MUST make sure to close the returned ReadCloser
func (s cs3) Retrieve(ctx context.Context, rID *provider.ResourceId) (io.ReadCloser, error) {
at, ok := contextGet(ctx, revactx.TokenHeader)
if !ok {
return nil, fmt.Errorf("context without %s", revactx.TokenHeader)
}
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
s.logger.Error().Err(err).Msg("could not get reva gatewayClient")
return nil, err
}
res, err := gatewayClient.InitiateFileDownload(ctx, &provider.InitiateFileDownloadRequest{Ref: &provider.Reference{ResourceId: rID, Path: "."}})
if err != nil {
return nil, err
}
if res.Status.Code != rpc.Code_CODE_OK {
return nil, fmt.Errorf("could not load resoure: %s", res.Status.Message)
}
var ep, tt string
for _, p := range res.Protocols {
if p.Protocol == "spaces" {
ep, tt = p.DownloadEndpoint, p.Token
break
}
}
if (ep == "" || tt == "") && len(res.Protocols) > 0 {
ep, tt = res.Protocols[0].DownloadEndpoint, res.Protocols[0].Token
}
req, err := http.NewRequest(http.MethodGet, ep, nil)
if err != nil {
return nil, err
}
req.Header.Set(revactx.TokenHeader, at)
req.Header.Set("X-Reva-Transfer", tt)
cres, err := s.httpClient.Do(req)
if err != nil {
return nil, err
}
if cres.StatusCode != http.StatusOK {
return nil, fmt.Errorf("could not download resource. Request returned with statuscode %d ", cres.StatusCode)
}
return cres.Body, nil
}