mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-20 03:20:44 -06:00
implement file sources
If the file is not cached we have to get it from somewhere. For that I implemented a webdav file source which gets the file from reva.
This commit is contained in:
@@ -89,7 +89,7 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "debug-addr",
|
||||
Value: "0.0.0.0:9114",
|
||||
Value: "0.0.0.0:9194",
|
||||
Usage: "Address to bind debug server",
|
||||
EnvVars: []string{"THUMBNAILS_DEBUG_ADDR"},
|
||||
Destination: &cfg.Debug.Addr,
|
||||
@@ -115,7 +115,7 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "http-addr",
|
||||
Value: "0.0.0.0:9110",
|
||||
Value: "0.0.0.0:9190",
|
||||
Usage: "Address to bind http server",
|
||||
EnvVars: []string{"THUMBNAILS_HTTP_ADDR"},
|
||||
Destination: &cfg.HTTP.Addr,
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/owncloud/ocis-thumbnails/pkg/config"
|
||||
"github.com/owncloud/ocis-thumbnails/pkg/thumbnails"
|
||||
"github.com/owncloud/ocis-thumbnails/pkg/thumbnails/cache"
|
||||
"github.com/owncloud/ocis-thumbnails/pkg/thumbnails/imgsource"
|
||||
)
|
||||
|
||||
// Service defines the extension handlers.
|
||||
@@ -29,6 +30,9 @@ func NewService(opts ...Option) Service {
|
||||
manager: thumbnails.SimpleManager{
|
||||
Cache: cache.NewInMemoryCache(),
|
||||
},
|
||||
source: imgsource.WebDav{
|
||||
Basepath: "http://localhost:9140/remote.php/webdav/",
|
||||
},
|
||||
}
|
||||
|
||||
m.Route(options.Config.HTTP.Root, func(r chi.Router) {
|
||||
@@ -43,6 +47,7 @@ type Thumbnails struct {
|
||||
config *config.Config
|
||||
mux *chi.Mux
|
||||
manager thumbnails.Manager
|
||||
source imgsource.Source
|
||||
}
|
||||
|
||||
// ServeHTTP implements the Service interface.
|
||||
@@ -53,27 +58,53 @@ func (g Thumbnails) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// Thumbnails provides the endpoint to retrieve a thumbnail for an image
|
||||
func (g Thumbnails) Thumbnails(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query()
|
||||
width, _ := strconv.Atoi(query.Get("w"))
|
||||
height, _ := strconv.Atoi(query.Get("h"))
|
||||
width, _ := strconv.Atoi(query.Get("width"))
|
||||
height, _ := strconv.Atoi(query.Get("height"))
|
||||
fileType := query.Get("type")
|
||||
fileID := query.Get("file_id")
|
||||
filePath := query.Get("file_path")
|
||||
|
||||
encoder := thumbnails.EncoderForType(fileType)
|
||||
if encoder == nil {
|
||||
// TODO: better error responses
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte("can't encode that"))
|
||||
return
|
||||
}
|
||||
ctx := thumbnails.ThumbnailContext{
|
||||
Width: width,
|
||||
Height: height,
|
||||
ImagePath: fileID,
|
||||
ImagePath: filePath,
|
||||
Encoder: encoder,
|
||||
}
|
||||
thumbnail, err := g.manager.Get(ctx)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
|
||||
thumbnail := g.manager.GetCached(ctx)
|
||||
if thumbnail != nil {
|
||||
w.Write(thumbnail)
|
||||
return
|
||||
}
|
||||
|
||||
auth := r.Header.Get("Authorization")
|
||||
|
||||
sCtx := imgsource.NewContext()
|
||||
sCtx.Set(imgsource.WebDavAuth, auth)
|
||||
// TODO: clean up error handling
|
||||
img, err := g.source.Get(ctx.ImagePath, sCtx)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
if img == nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte("img is nil"))
|
||||
return
|
||||
}
|
||||
thumbnail, err = g.manager.Get(ctx, img)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write(thumbnail)
|
||||
}
|
||||
|
||||
33
pkg/thumbnails/imgsource/imgsource.go
Normal file
33
pkg/thumbnails/imgsource/imgsource.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package imgsource
|
||||
|
||||
import "image"
|
||||
|
||||
// Source defines the interface for image sources
|
||||
type Source interface {
|
||||
Get(path string, ctx SourceContext) (image.Image, error)
|
||||
}
|
||||
|
||||
// NewContext creates a new SourceContext instance
|
||||
func NewContext() SourceContext {
|
||||
return SourceContext{
|
||||
m: make(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
// SourceContext is used to pass source specific parameters
|
||||
type SourceContext struct {
|
||||
m map[string]interface{}
|
||||
}
|
||||
|
||||
// GetString tries to cast the value to a string
|
||||
func (s SourceContext) GetString(key string) string {
|
||||
if s, ok := s.m[key].(string); ok {
|
||||
return s
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Set sets a value
|
||||
func (s SourceContext) Set(key string, val interface{}) {
|
||||
s.m[key] = val
|
||||
}
|
||||
41
pkg/thumbnails/imgsource/webdav.go
Normal file
41
pkg/thumbnails/imgsource/webdav.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package imgsource
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
)
|
||||
|
||||
// WebDav implements the Source interface for webdav services
|
||||
type WebDav struct {
|
||||
Basepath string
|
||||
}
|
||||
|
||||
const (
|
||||
// WebDavAuth is the parameter name for the autorization token
|
||||
WebDavAuth = "Authorization"
|
||||
)
|
||||
|
||||
// Get downloads the file from a webdav service
|
||||
func (s WebDav) Get(file string, ctx SourceContext) (image.Image, error) {
|
||||
u, _ := url.Parse(s.Basepath)
|
||||
u.Path = path.Join(u.Path, file)
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get the file %s error: %s", file, err.Error())
|
||||
}
|
||||
|
||||
auth := ctx.GetString(WebDavAuth)
|
||||
req.Header.Add("Authorization", auth)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get the file %s error: %s", file, err.Error())
|
||||
}
|
||||
|
||||
img, _, _ := image.Decode(resp.Body)
|
||||
return img, nil
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package thumbnails
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -16,14 +15,13 @@ type ThumbnailContext struct {
|
||||
Width int
|
||||
Height int
|
||||
ImagePath string
|
||||
|
||||
Encoder Encoder
|
||||
Encoder Encoder
|
||||
}
|
||||
|
||||
// Manager is responsible for generating thumbnails
|
||||
type Manager interface {
|
||||
// Get will return a thumbnail for a file
|
||||
Get(ThumbnailContext) ([]byte, error)
|
||||
Get(ThumbnailContext, image.Image) ([]byte, error)
|
||||
GetCached(ThumbnailContext) []byte
|
||||
}
|
||||
|
||||
@@ -33,18 +31,14 @@ type SimpleManager struct {
|
||||
}
|
||||
|
||||
// Get implements the Get Method of Manager
|
||||
func (s SimpleManager) Get(ctx ThumbnailContext) ([]byte, error) {
|
||||
key := buildCacheKey(ctx)
|
||||
func (s SimpleManager) Get(ctx ThumbnailContext, img image.Image) ([]byte, error) {
|
||||
thumbnail := s.generate(ctx, img)
|
||||
|
||||
cached := s.Cache.Get(key)
|
||||
if cached == nil {
|
||||
thumbnail := s.generate(ctx)
|
||||
s.Cache.Set(key, thumbnail)
|
||||
cached = thumbnail
|
||||
}
|
||||
key := buildCacheKey(ctx)
|
||||
s.Cache.Set(key, thumbnail)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err := ctx.Encoder.Encode(buf, cached)
|
||||
err := ctx.Encoder.Encode(buf, thumbnail)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -64,15 +58,11 @@ func (s SimpleManager) GetCached(ctx ThumbnailContext) []byte {
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (s SimpleManager) generate(ctx ThumbnailContext) image.Image {
|
||||
func (s SimpleManager) generate(ctx ThumbnailContext, img image.Image) image.Image {
|
||||
// TODO: remove, just for demo purposes
|
||||
time.Sleep(time.Second * 2)
|
||||
|
||||
// TODO: get file from reva
|
||||
reader, _ := os.Open(ctx.ImagePath)
|
||||
defer reader.Close()
|
||||
m, _, _ := image.Decode(reader)
|
||||
thumbnail := resize.Thumbnail(uint(ctx.Width), uint(ctx.Height), m, resize.Lanczos2)
|
||||
thumbnail := resize.Thumbnail(uint(ctx.Width), uint(ctx.Height), img, resize.Lanczos2)
|
||||
return thumbnail
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user