From 02e23ebac4c99070e2135f43613280fafc3f45ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20G=C3=A4hwiler?= Date: Fri, 1 Mar 2024 16:03:11 +0100 Subject: [PATCH] blaze: added redirect bucket method --- blaze/bucket.go | 41 ++++++++++++++++++++++++ blaze/bucket_test.go | 74 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/blaze/bucket.go b/blaze/bucket.go index b403aa91..b03de610 100644 --- a/blaze/bucket.go +++ b/blaze/bucket.go @@ -1055,6 +1055,47 @@ func (b *Bucket) DownloadAction(timeout time.Duration) *fire.Action { }) } +// RedirectAction will construct an action that will redirect to the specified +// endpoint with the view key of the file in the specified field. The endpoint +// should be the relative or absolute URL of the blaze download endpoint. +func (b *Bucket) RedirectAction(field, endpoint string) *fire.Action { + return fire.A("blaze/Redirect", []string{"GET"}, 0, 0, func(ctx *fire.Context) error { + // lookup field + value := stick.MustGet(ctx.Model, field) + + // get link + var id coal.ID + switch value := value.(type) { + case Link: + id = value.File + case *Link: + if value != nil { + id = value.File + } + } + + // handle absence + if id.IsZero() { + ctx.ResponseWriter.WriteHeader(http.StatusNotFound) + return nil + } + + // get view key + key, err := b.GetViewKey(ctx, id) + if err != nil { + return err + } + + // construct URL + url := endpoint + "?key=" + key + + // perform redirect + http.Redirect(ctx.ResponseWriter, ctx.HTTPRequest, url, http.StatusSeeOther) + + return nil + }) +} + // CleanupFile will clean up a single file. In the first step, files in the // uploading or uploaded state are marked as "deleting". In the second step, // blobs of "deleting" files are deleted. In the last step "deleting" files with diff --git a/blaze/bucket_test.go b/blaze/bucket_test.go index 7b164e2b..8cef25ec 100644 --- a/blaze/bucket_test.go +++ b/blaze/bucket_test.go @@ -1346,6 +1346,80 @@ func TestBucketDownloadActionStream(t *testing.T) { }) } +func TestBucketRedirectAction(t *testing.T) { + withTester(t, func(t *testing.T, tester *fire.Tester) { + bucket := NewBucket(tester.Store, testNotary, bindings.All()...) + bucket.Use(NewMemory(), "default", true) + + id := coal.New() + key, _ := bucket.GetViewKey(nil, id) + reqAction := bucket.RedirectAction("RequiredFile", "/download") + optAction := bucket.RedirectAction("OptionalFile", "/download") + + /* zero required link */ + + req := httptest.NewRequest("GET", "/", nil) + rec, err := tester.RunAction(&fire.Context{ + Model: &testModel{}, + HTTPRequest: req, + }, reqAction) + assert.NoError(t, err) + assert.Equal(t, http.StatusNotFound, rec.Code) + assert.Equal(t, http.Header{}, rec.Header()) + assert.Equal(t, "", rec.Body.String()) + + /* present required link */ + + req = httptest.NewRequest("GET", "/", nil) + rec, err = tester.RunAction(&fire.Context{ + Model: &testModel{ + RequiredFile: Link{ + File: id, + }, + }, + HTTPRequest: req, + }, reqAction) + assert.NoError(t, err) + assert.Equal(t, http.StatusSeeOther, rec.Code) + assert.Equal(t, http.Header{ + "Content-Type": []string{"text/html; charset=utf-8"}, + "Location": []string{"/download?key=" + key}, + }, rec.Header()) + assert.Equal(t, `See Other.`, strings.TrimSpace(rec.Body.String())) + + /* absent optional link */ + + req = httptest.NewRequest("GET", "/", nil) + rec, err = tester.RunAction(&fire.Context{ + Model: &testModel{}, + HTTPRequest: req, + }, optAction) + assert.NoError(t, err) + assert.Equal(t, http.StatusNotFound, rec.Code) + assert.Equal(t, http.Header{}, rec.Header()) + assert.Equal(t, "", rec.Body.String()) + + /* present required link */ + + req = httptest.NewRequest("GET", "/", nil) + rec, err = tester.RunAction(&fire.Context{ + Model: &testModel{ + OptionalFile: &Link{ + File: id, + }, + }, + HTTPRequest: req, + }, optAction) + assert.NoError(t, err) + assert.Equal(t, http.StatusSeeOther, rec.Code) + assert.Equal(t, http.Header{ + "Content-Type": []string{"text/html; charset=utf-8"}, + "Location": []string{"/download?key=" + key}, + }, rec.Header()) + assert.Equal(t, `See Other.`, strings.TrimSpace(rec.Body.String())) + }) +} + func TestBucketCleanup(t *testing.T) { withTester(t, func(t *testing.T, tester *fire.Tester) { svc := NewMemory()