Skip to content

Commit f8aa2df

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

File tree

2 files changed

+94
-27
lines changed

2 files changed

+94
-27
lines changed

thumbnails/handler.go

Lines changed: 40 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,53 @@ 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+
case "public-files":
161+
if !checkMethods(r, http.MethodGet, http.MethodHead) {
162+
w.WriteHeader(http.StatusNotFound)
163+
return
164+
}
165+
s.davPublicContext(s.Thumbnail(w, r)).ServeHTTP(w, r)
166+
}
167+
})
168+
}
169+
146170
func (s *Thumbnails) davUserContext(next http.Handler) http.Handler {
147171
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
148172
ctx := r.Context()
173+
log := appctx.GetLogger(ctx)
149174

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

153185
res, err := s.statRes(ctx, &provider.Reference{
154-
Path: path,
186+
Path: resourcePath,
155187
})
156188
if err != nil {
157189
s.writeHTTPError(w, err)
158190
return
159191
}
160192

161193
ctx = ContextSetResource(ctx, res)
194+
log.Info().Msgf("FindMe - set resource %s", res.Path)
162195

163196
next.ServeHTTP(w, r.WithContext(ctx))
164197
})
@@ -365,12 +398,16 @@ func parseDimension(d, name string, defaultValue int) (int, error) {
365398
func (s *Thumbnails) Thumbnail(w http.ResponseWriter, r *http.Request) http.Handler {
366399
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
367400
thumbReq, err := s.parseThumbnailRequest(r)
401+
log := appctx.GetLogger(r.Context())
402+
log.Info().Msgf("FindMe - Handling thumbnail request %s", thumbReq.File)
368403
if err != nil {
369404
s.writeHTTPError(w, err)
370405
return
371406
}
372407

373408
data, mimetype, err := s.thumbnail.GetThumbnail(r.Context(), thumbReq.File, thumbReq.ETag, thumbReq.Width, thumbReq.Height, thumbReq.OutputType)
409+
log.Info().Msgf("FindMe - Got thumbnail for %s", thumbReq.File)
410+
374411
if err != nil {
375412
s.writeHTTPError(w, err)
376413
return
@@ -402,29 +439,6 @@ func (s *Thumbnails) writeHTTPError(w http.ResponseWriter, err error) {
402439
_, _ = w.Write([]byte(err.Error()))
403440
}
404441

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-
428442
func checkMethods(r *http.Request, methods ...string) bool {
429443
for _, m := range methods {
430444
if r.Method == m {

thumbnails/manager/thumbnail.go

Lines changed: 54 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().Err(err).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,38 @@ 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+
_, _, err := image.DecodeConfig(bytes.NewReader(imgBody))
165+
if err != nil {
166+
errCh <- err
167+
return
168+
}
169+
170+
img, _, err := image.Decode(bytes.NewReader(imgBody))
171+
if err != nil {
172+
errCh <- err
173+
return
174+
}
175+
resultCh <- img
176+
}()
177+
178+
select {
179+
case <-ctx.Done():
180+
return nil, ctx.Err() // context deadline exceeded
181+
case err := <-errCh:
182+
return nil, err
183+
case img := <-resultCh:
184+
return img, nil
185+
}
186+
}
187+
135188
func getMimeType(ttype FileType) string {
136189
switch ttype {
137190
case PNGType:

0 commit comments

Comments
 (0)