You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cloudreve/pkg/wopi/discovery.go

102 lines
2.3 KiB

package wopi
import (
"encoding/xml"
"fmt"
"github.com/cloudreve/Cloudreve/v3/pkg/util"
"net/http"
"strings"
)
type ActonType string
var (
ActionPreview = ActonType("embedview")
ActionPreviewFallback = ActonType("view")
ActionEdit = ActonType("edit")
)
const (
DiscoverResponseCacheKey = "wopi_discover"
DiscoverRefreshDuration = 24 * 3600 // 24 hrs
)
func (c *client) AvailableExts() []string {
if err := c.checkDiscovery(); err != nil {
util.Log().Error("Failed to check WOPI discovery: %s", err)
return nil
}
c.mu.RLock()
defer c.mu.RUnlock()
exts := make([]string, 0, len(c.actions))
for ext, actions := range c.actions {
_, previewable := actions[string(ActionPreview)]
_, editable := actions[string(ActionEdit)]
_, previewableFallback := actions[string(ActionPreviewFallback)]
if previewable || editable || previewableFallback {
exts = append(exts, strings.TrimPrefix(ext, "."))
}
}
return exts
}
// checkDiscovery checks if discovery content is needed to be refreshed.
// If so, it will refresh discovery content.
func (c *client) checkDiscovery() error {
c.mu.RLock()
if c.discovery == nil {
c.mu.RUnlock()
return c.refreshDiscovery()
}
c.mu.RUnlock()
return nil
}
// refresh Discovery action configs.
func (c *client) refreshDiscovery() error {
c.mu.Lock()
defer c.mu.Unlock()
cached, exist := c.cache.Get(DiscoverResponseCacheKey)
if exist {
cachedDiscovery := cached.(WopiDiscovery)
c.discovery = &cachedDiscovery
} else {
res, err := c.http.Request("GET", c.config.discoveryEndpoint.String(), nil).
CheckHTTPResponse(http.StatusOK).GetResponse()
if err != nil {
return fmt.Errorf("failed to request discovery endpoint: %w", err)
}
if err := xml.Unmarshal([]byte(res), &c.discovery); err != nil {
return fmt.Errorf("failed to parse response discovery endpoint: %w", err)
}
if err := c.cache.Set(DiscoverResponseCacheKey, *c.discovery, DiscoverRefreshDuration); err != nil {
return err
}
}
// construct actions map
c.actions = make(map[string]map[string]Action)
for _, app := range c.discovery.NetZone.App {
for _, action := range app.Action {
if action.Ext == "" {
continue
}
if _, ok := c.actions["."+action.Ext]; !ok {
c.actions["."+action.Ext] = make(map[string]Action)
}
c.actions["."+action.Ext][action.Name] = action
}
}
return nil
}