Skip to content

Commit da21b7b

Browse files
committed
Fix: make thumbnails processor to work with spaces
1 parent 4715941 commit da21b7b

File tree

2 files changed

+89
-27
lines changed

2 files changed

+89
-27
lines changed

thumbnails/handler.go

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"io"
2727
"net/http"
2828
"net/url"
29+
"path"
2930
"path/filepath"
3031
"strconv"
3132
"strings"
@@ -45,6 +46,7 @@ import (
4546
"github.com/cs3org/reva/v3/pkg/rhttp/global"
4647
"github.com/cs3org/reva/v3/pkg/rhttp/router"
4748
"github.com/cs3org/reva/v3/pkg/sharedconf"
49+
"github.com/cs3org/reva/v3/pkg/spaces"
4850
"github.com/cs3org/reva/v3/pkg/storage/utils/downloader"
4951
"github.com/cs3org/reva/v3/pkg/utils/cfg"
5052
"github.com/pkg/errors"
@@ -143,22 +145,54 @@ func New(ctx context.Context, m map[string]interface{}) (global.Service, error)
143145
return s, nil
144146
}
145147

148+
func (s *Thumbnails) Handler() http.Handler {
149+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
150+
var head string
151+
152+
head, r.URL.Path = router.ShiftPath(r.URL.Path)
153+
switch head {
154+
case "files":
155+
if !checkMethods(r, http.MethodGet) {
156+
w.WriteHeader(http.StatusNotFound)
157+
return
158+
}
159+
s.davUserContext(s.Thumbnail(w, r)).ServeHTTP(w, r)
160+
return
161+
case "public-files":
162+
if !checkMethods(r, http.MethodGet, http.MethodHead) {
163+
w.WriteHeader(http.StatusNotFound)
164+
return
165+
}
166+
s.davPublicContext(s.Thumbnail(w, r)).ServeHTTP(w, r)
167+
}
168+
})
169+
}
170+
146171
func (s *Thumbnails) davUserContext(next http.Handler) http.Handler {
147172
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
148173
ctx := r.Context()
174+
log := appctx.GetLogger(ctx)
175+
176+
urlPath, _ := url.PathUnescape(r.URL.Path)
149177

150-
path := r.URL.Path
151-
path, _ = url.PathUnescape(path)
178+
storageSpaceID, resourcePath := router.ShiftPath(urlPath)
179+
_, spacePath, ok := spaces.DecodeStorageSpaceID(storageSpaceID)
180+
if !ok {
181+
s.writeHTTPError(w, errtypes.NotFound(""))
182+
return
183+
}
184+
resourcePath = path.Join(spacePath, resourcePath)
152185

153186
res, err := s.statRes(ctx, &provider.Reference{
154-
Path: path,
187+
Path: resourcePath,
155188
})
156189
if err != nil {
157190
s.writeHTTPError(w, err)
158191
return
159192
}
160193

161194
ctx = ContextSetResource(ctx, res)
195+
log.Info().Msgf("FindMe - set resource %s", res.Path)
162196

163197
next.ServeHTTP(w, r.WithContext(ctx))
164198
})
@@ -365,12 +399,16 @@ func parseDimension(d, name string, defaultValue int) (int, error) {
365399
func (s *Thumbnails) Thumbnail(w http.ResponseWriter, r *http.Request) http.Handler {
366400
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
367401
thumbReq, err := s.parseThumbnailRequest(r)
402+
log := appctx.GetLogger(r.Context())
403+
log.Info().Msgf("FindMe - Handling thumbnail request %s", thumbReq.File)
368404
if err != nil {
369405
s.writeHTTPError(w, err)
370406
return
371407
}
372408

373409
data, mimetype, err := s.thumbnail.GetThumbnail(r.Context(), thumbReq.File, thumbReq.ETag, thumbReq.Width, thumbReq.Height, thumbReq.OutputType)
410+
log.Info().Msgf("FindMe - Got thumbnail for %s", thumbReq.File)
411+
374412
if err != nil {
375413
s.writeHTTPError(w, err)
376414
return
@@ -402,29 +440,6 @@ func (s *Thumbnails) writeHTTPError(w http.ResponseWriter, err error) {
402440
_, _ = w.Write([]byte(err.Error()))
403441
}
404442

405-
func (s *Thumbnails) Handler() http.Handler {
406-
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
407-
var head string
408-
409-
head, r.URL.Path = router.ShiftPath(r.URL.Path)
410-
switch head {
411-
case "files":
412-
if !checkMethods(r, http.MethodGet) {
413-
w.WriteHeader(http.StatusNotFound)
414-
return
415-
}
416-
s.davUserContext(s.Thumbnail(w, r)).ServeHTTP(w, r)
417-
return
418-
case "public-files":
419-
if !checkMethods(r, http.MethodGet, http.MethodHead) {
420-
w.WriteHeader(http.StatusNotFound)
421-
return
422-
}
423-
s.davPublicContext(s.Thumbnail(w, r)).ServeHTTP(w, r)
424-
}
425-
})
426-
}
427-
428443
func checkMethods(r *http.Request, methods ...string) bool {
429444
for _, m := range methods {
430445
if r.Method == m {

thumbnails/manager/thumbnail.go

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"context"
2424
"fmt"
2525
"image"
26+
"io"
27+
"time"
2628

2729
"github.com/cernbox/reva-plugins/thumbnails/cache"
2830
"github.com/cernbox/reva-plugins/thumbnails/cache/registry"
@@ -35,6 +37,10 @@ import (
3537

3638
// load all the cache drivers
3739
_ "github.com/cernbox/reva-plugins/thumbnails/cache/loader"
40+
41+
_ "image/gif"
42+
_ "image/jpeg"
43+
_ "image/png"
3844
)
3945

4046
// FileType is the output format of the thumbnail
@@ -99,30 +105,45 @@ func (t *Thumbnail) GetThumbnail(ctx context.Context, file, etag string, width,
99105
log.Debug().Msg("thumbnails: cache miss")
100106

101107
// the thumbnail was not found in the cache
108+
log.Debug().Msgf("thumbnails: starting download %s", file)
102109
r, err := t.downloader.Download(ctx, file, "")
110+
log.Debug().Msgf("thumbnails: finished download %s", file)
103111
if err != nil {
104112
return nil, "", errors.Wrap(err, "thumbnails: error downloading file "+file)
105113
}
106114
defer r.Close()
115+
imgBody, err := io.ReadAll(r)
116+
log.Debug().Msgf("thumbnails: finished read %s", file)
117+
118+
if err != nil {
119+
log.Error().Err(err).Msg("Failed to read IO")
120+
return nil, "", errors.Wrap(err, "thumbnails: failed to read file "+file)
121+
122+
}
123+
img, err := decodeWithTimeout(ctx, imgBody, 2)
124+
log.Debug().Msgf("thumbnails: finished decoding %s", file)
107125

108-
img, _, err := image.Decode(r)
109126
if err != nil {
110127
return nil, "", errors.Wrap(err, "thumbnails: error decoding file "+file)
111128
}
112129

113130
resolution := image.Rect(0, 0, width, height)
114131
match := t.fixedResolutions.MatchOrResize(resolution, img.Bounds())
115132
thumb := imaging.Thumbnail(img, match.Dx(), match.Dy(), imaging.Linear)
133+
log.Debug().Msgf("thumbnails: finished resize %s", file)
116134

117135
var buf bytes.Buffer
118136
format, opts := t.getEncoderFormat(outType)
119137
err = imaging.Encode(&buf, thumb, format, opts...)
120138
if err != nil {
121139
return nil, "", errors.Wrap(err, "thumbnails: error encoding image")
122140
}
141+
log.Debug().Msgf("thumbnails: finished re-encoding %s", file)
123142

124143
data := buf.Bytes()
125144
err = t.cache.Set(file, etag, width, height, data)
145+
log.Debug().Msgf("thumbnails: set cache %s", file)
146+
126147
if err != nil {
127148
log.Warn().Msg("failed to save data into the cache")
128149
} else {
@@ -132,6 +153,32 @@ func (t *Thumbnail) GetThumbnail(ctx context.Context, file, etag string, width,
132153
return data, getMimeType(outType), nil
133154
}
134155

156+
func decodeWithTimeout(ctx context.Context, imgBody []byte, timeoutSec time.Duration) (image.Image, error) {
157+
ctx, cancel := context.WithTimeout(ctx, timeoutSec*time.Second)
158+
defer cancel()
159+
160+
resultCh := make(chan image.Image, 1)
161+
errCh := make(chan error, 1)
162+
163+
go func() {
164+
img, _, err := image.Decode(bytes.NewReader(imgBody))
165+
if err != nil {
166+
errCh <- err
167+
return
168+
}
169+
resultCh <- img
170+
}()
171+
172+
select {
173+
case <-ctx.Done():
174+
return nil, ctx.Err() // context deadline exceeded
175+
case err := <-errCh:
176+
return nil, err
177+
case img := <-resultCh:
178+
return img, nil
179+
}
180+
}
181+
135182
func getMimeType(ttype FileType) string {
136183
switch ttype {
137184
case PNGType:

0 commit comments

Comments
 (0)