[#7268] added FileDownloadRequestEvent.ThumbError field
This commit is contained in:
parent
7b52d0b56a
commit
83a26d436e
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
- Support Ed25519 in the optional OIDC id_token signature validation ([#7252](https://github.com/pocketbase/pocketbase/issues/7252); thanks @shynome).
|
- Support Ed25519 in the optional OIDC id_token signature validation ([#7252](https://github.com/pocketbase/pocketbase/issues/7252); thanks @shynome).
|
||||||
|
|
||||||
- Added `tests.ApiScenario.DisableTestAppCleanup` optional field to skip the auto test app cleanup and leave it up to the developers ([#7267](https://github.com/pocketbase/pocketbase/discussions/7267)).
|
- Added `ApiScenario.DisableTestAppCleanup` optional field to skip the auto test app cleanup and leave it up to the developers ([#7267](https://github.com/pocketbase/pocketbase/discussions/7267)).
|
||||||
|
|
||||||
|
- Added `FileDownloadRequestEvent.ThumbError` field that will be populated in case of a thumb generation failure (e.g. unsupported format, timing out, etc.), allow developers to reject the fallback and/or supply their own custom thumb generation ([#7268](https://github.com/pocketbase/pocketbase/discussions/7268)).
|
||||||
|
|
||||||
|
|
||||||
## v0.30.4
|
## v0.30.4
|
||||||
|
|
|
||||||
37
apis/file.go
37
apis/file.go
|
|
@ -142,8 +142,14 @@ func (api *fileApi) download(e *core.RequestEvent) error {
|
||||||
defer fsys.Close()
|
defer fsys.Close()
|
||||||
|
|
||||||
originalPath := baseFilesPath + "/" + filename
|
originalPath := baseFilesPath + "/" + filename
|
||||||
servedPath := originalPath
|
|
||||||
servedName := filename
|
event := new(core.FileDownloadRequestEvent)
|
||||||
|
event.RequestEvent = e
|
||||||
|
event.Collection = collection
|
||||||
|
event.Record = record
|
||||||
|
event.FileField = fileField
|
||||||
|
event.ServedPath = originalPath
|
||||||
|
event.ServedName = filename
|
||||||
|
|
||||||
// check for valid thumb size param
|
// check for valid thumb size param
|
||||||
thumbSize := e.Request.URL.Query().Get("thumb")
|
thumbSize := e.Request.URL.Query().Get("thumb")
|
||||||
|
|
@ -157,34 +163,31 @@ func (api *fileApi) download(e *core.RequestEvent) error {
|
||||||
// check if it is an image
|
// check if it is an image
|
||||||
if list.ExistInSlice(oAttrs.ContentType, imageContentTypes) {
|
if list.ExistInSlice(oAttrs.ContentType, imageContentTypes) {
|
||||||
// add thumb size as file suffix
|
// add thumb size as file suffix
|
||||||
servedName = thumbSize + "_" + filename
|
event.ServedName = thumbSize + "_" + filename
|
||||||
servedPath = baseFilesPath + "/thumbs_" + filename + "/" + servedName
|
event.ServedPath = baseFilesPath + "/thumbs_" + filename + "/" + event.ServedName
|
||||||
|
|
||||||
// create a new thumb if it doesn't exist
|
// create a new thumb if it doesn't exist
|
||||||
if exists, _ := fsys.Exists(servedPath); !exists {
|
if exists, _ := fsys.Exists(event.ServedPath); !exists {
|
||||||
if err := api.createThumb(e, fsys, originalPath, servedPath, thumbSize); err != nil {
|
if err := api.createThumb(e, fsys, originalPath, event.ServedPath, thumbSize); err != nil {
|
||||||
e.App.Logger().Warn(
|
e.App.Logger().Warn(
|
||||||
"Fallback to original - failed to create thumb "+servedName,
|
"Fallback to original - failed to create thumb "+event.ServedName,
|
||||||
slog.Any("error", err),
|
slog.Any("error", err),
|
||||||
slog.String("original", originalPath),
|
slog.String("original", originalPath),
|
||||||
slog.String("thumb", servedPath),
|
slog.String("thumb", event.ServedPath),
|
||||||
)
|
)
|
||||||
|
|
||||||
// fallback to the original
|
// fallback to the original
|
||||||
servedName = filename
|
event.ThumbError = err
|
||||||
servedPath = originalPath
|
event.ServedName = filename
|
||||||
|
event.ServedPath = originalPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event := new(core.FileDownloadRequestEvent)
|
if thumbSize != "" && event.ThumbError == nil && event.ServedPath == originalPath {
|
||||||
event.RequestEvent = e
|
event.ThumbError = fmt.Errorf("the thumb size %q is not supported", thumbSize)
|
||||||
event.Collection = collection
|
}
|
||||||
event.Record = record
|
|
||||||
event.FileField = fileField
|
|
||||||
event.ServedPath = servedPath
|
|
||||||
event.ServedName = servedName
|
|
||||||
|
|
||||||
// clickjacking shouldn't be a concern when serving uploaded files,
|
// clickjacking shouldn't be a concern when serving uploaded files,
|
||||||
// so it safe to unset the global X-Frame-Options to allow files embedding
|
// so it safe to unset the global X-Frame-Options to allow files embedding
|
||||||
|
|
|
||||||
|
|
@ -181,9 +181,17 @@ func TestFileDownload(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "existing image - missing thumb (should fallback to the original)",
|
Name: "existing image - missing thumb (should fallback to the original)",
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=999x999",
|
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=999x999",
|
||||||
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||||
|
app.OnFileDownloadRequest().BindFunc(func(e *core.FileDownloadRequestEvent) error {
|
||||||
|
if e.ThumbError == nil {
|
||||||
|
t.Fatal("Expected thumb error, got nil")
|
||||||
|
}
|
||||||
|
return e.Next()
|
||||||
|
})
|
||||||
|
},
|
||||||
ExpectedStatus: 200,
|
ExpectedStatus: 200,
|
||||||
ExpectedContent: []string{string(testImg)},
|
ExpectedContent: []string{string(testImg)},
|
||||||
ExpectedEvents: map[string]int{
|
ExpectedEvents: map[string]int{
|
||||||
|
|
@ -192,9 +200,17 @@ func TestFileDownload(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "existing image - existing thumb (crop center)",
|
Name: "existing image - existing thumb (crop center)",
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x50",
|
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x50",
|
||||||
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||||
|
app.OnFileDownloadRequest().BindFunc(func(e *core.FileDownloadRequestEvent) error {
|
||||||
|
if e.ThumbError != nil {
|
||||||
|
t.Fatalf("Expected no thumb error, got %v", e.ThumbError)
|
||||||
|
}
|
||||||
|
return e.Next()
|
||||||
|
})
|
||||||
|
},
|
||||||
ExpectedStatus: 200,
|
ExpectedStatus: 200,
|
||||||
ExpectedContent: []string{string(testThumbCropCenter)},
|
ExpectedContent: []string{string(testThumbCropCenter)},
|
||||||
ExpectedEvents: map[string]int{
|
ExpectedEvents: map[string]int{
|
||||||
|
|
@ -203,9 +219,17 @@ func TestFileDownload(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "existing image - existing thumb (crop top)",
|
Name: "existing image - existing thumb (crop top)",
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x50t",
|
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x50t",
|
||||||
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||||
|
app.OnFileDownloadRequest().BindFunc(func(e *core.FileDownloadRequestEvent) error {
|
||||||
|
if e.ThumbError != nil {
|
||||||
|
t.Fatalf("Expected no thumb error, got %v", e.ThumbError)
|
||||||
|
}
|
||||||
|
return e.Next()
|
||||||
|
})
|
||||||
|
},
|
||||||
ExpectedStatus: 200,
|
ExpectedStatus: 200,
|
||||||
ExpectedContent: []string{string(testThumbCropTop)},
|
ExpectedContent: []string{string(testThumbCropTop)},
|
||||||
ExpectedEvents: map[string]int{
|
ExpectedEvents: map[string]int{
|
||||||
|
|
@ -214,9 +238,17 @@ func TestFileDownload(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "existing image - existing thumb (crop bottom)",
|
Name: "existing image - existing thumb (crop bottom)",
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x50b",
|
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x50b",
|
||||||
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||||
|
app.OnFileDownloadRequest().BindFunc(func(e *core.FileDownloadRequestEvent) error {
|
||||||
|
if e.ThumbError != nil {
|
||||||
|
t.Fatalf("Expected no thumb error, got %v", e.ThumbError)
|
||||||
|
}
|
||||||
|
return e.Next()
|
||||||
|
})
|
||||||
|
},
|
||||||
ExpectedStatus: 200,
|
ExpectedStatus: 200,
|
||||||
ExpectedContent: []string{string(testThumbCropBottom)},
|
ExpectedContent: []string{string(testThumbCropBottom)},
|
||||||
ExpectedEvents: map[string]int{
|
ExpectedEvents: map[string]int{
|
||||||
|
|
@ -225,9 +257,17 @@ func TestFileDownload(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "existing image - existing thumb (fit)",
|
Name: "existing image - existing thumb (fit)",
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x50f",
|
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x50f",
|
||||||
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||||
|
app.OnFileDownloadRequest().BindFunc(func(e *core.FileDownloadRequestEvent) error {
|
||||||
|
if e.ThumbError != nil {
|
||||||
|
t.Fatalf("Expected no thumb error, got %v", e.ThumbError)
|
||||||
|
}
|
||||||
|
return e.Next()
|
||||||
|
})
|
||||||
|
},
|
||||||
ExpectedStatus: 200,
|
ExpectedStatus: 200,
|
||||||
ExpectedContent: []string{string(testThumbFit)},
|
ExpectedContent: []string{string(testThumbFit)},
|
||||||
ExpectedEvents: map[string]int{
|
ExpectedEvents: map[string]int{
|
||||||
|
|
@ -236,9 +276,17 @@ func TestFileDownload(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "existing image - existing thumb (zero width)",
|
Name: "existing image - existing thumb (zero width)",
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=0x50",
|
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=0x50",
|
||||||
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||||
|
app.OnFileDownloadRequest().BindFunc(func(e *core.FileDownloadRequestEvent) error {
|
||||||
|
if e.ThumbError != nil {
|
||||||
|
t.Fatalf("Expected no thumb error, got %v", e.ThumbError)
|
||||||
|
}
|
||||||
|
return e.Next()
|
||||||
|
})
|
||||||
|
},
|
||||||
ExpectedStatus: 200,
|
ExpectedStatus: 200,
|
||||||
ExpectedContent: []string{string(testThumbZeroWidth)},
|
ExpectedContent: []string{string(testThumbZeroWidth)},
|
||||||
ExpectedEvents: map[string]int{
|
ExpectedEvents: map[string]int{
|
||||||
|
|
@ -247,9 +295,17 @@ func TestFileDownload(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "existing image - existing thumb (zero height)",
|
Name: "existing image - existing thumb (zero height)",
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x0",
|
URL: "/api/files/_pb_users_auth_/4q1xlclmfloku33/300_1SEi6Q6U72.png?thumb=70x0",
|
||||||
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||||
|
app.OnFileDownloadRequest().BindFunc(func(e *core.FileDownloadRequestEvent) error {
|
||||||
|
if e.ThumbError != nil {
|
||||||
|
t.Fatalf("Expected no thumb error, got %v", e.ThumbError)
|
||||||
|
}
|
||||||
|
return e.Next()
|
||||||
|
})
|
||||||
|
},
|
||||||
ExpectedStatus: 200,
|
ExpectedStatus: 200,
|
||||||
ExpectedContent: []string{string(testThumbZeroHeight)},
|
ExpectedContent: []string{string(testThumbZeroHeight)},
|
||||||
ExpectedEvents: map[string]int{
|
ExpectedEvents: map[string]int{
|
||||||
|
|
@ -258,9 +314,17 @@ func TestFileDownload(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "existing non image file - thumb parameter should be ignored",
|
Name: "existing non image file - thumb parameter should be ignored",
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
URL: "/api/files/_pb_users_auth_/oap640cot4yru2s/test_kfd2wYLxkz.txt?thumb=100x100",
|
URL: "/api/files/_pb_users_auth_/oap640cot4yru2s/test_kfd2wYLxkz.txt?thumb=100x100",
|
||||||
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||||
|
app.OnFileDownloadRequest().BindFunc(func(e *core.FileDownloadRequestEvent) error {
|
||||||
|
if e.ThumbError == nil {
|
||||||
|
t.Fatal("Expected thumb error, got nil")
|
||||||
|
}
|
||||||
|
return e.Next()
|
||||||
|
})
|
||||||
|
},
|
||||||
ExpectedStatus: 200,
|
ExpectedStatus: 200,
|
||||||
ExpectedContent: []string{string(testFile)},
|
ExpectedContent: []string{string(testFile)},
|
||||||
ExpectedEvents: map[string]int{
|
ExpectedEvents: map[string]int{
|
||||||
|
|
|
||||||
|
|
@ -384,6 +384,13 @@ type FileDownloadRequestEvent struct {
|
||||||
FileField *FileField
|
FileField *FileField
|
||||||
ServedPath string
|
ServedPath string
|
||||||
ServedName string
|
ServedName string
|
||||||
|
|
||||||
|
// ThumbError indicates the a thumb wasn't able to be generated
|
||||||
|
// (e.g. because it didn't satisfy the support image formats or it timed out).
|
||||||
|
//
|
||||||
|
// Note that PocketBase fallbacks to the original file in case of a thumb error,
|
||||||
|
// but developers can check the field and provide their own custom thumb generation if necessary.
|
||||||
|
ThumbError error
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue