diff --git a/pkg/api/resolver_model_image.go b/pkg/api/resolver_model_image.go index d3cf4c066..893198f1c 100644 --- a/pkg/api/resolver_model_image.go +++ b/pkg/api/resolver_model_image.go @@ -34,7 +34,7 @@ func (r *imageResolver) File(ctx context.Context, obj *models.Image) (*models.Im func (r *imageResolver) Paths(ctx context.Context, obj *models.Image) (*models.ImagePathsType, error) { baseURL, _ := ctx.Value(BaseURLCtxKey).(string) - builder := urlbuilders.NewImageURLBuilder(baseURL, obj.ID) + builder := urlbuilders.NewImageURLBuilder(baseURL, obj) thumbnailPath := builder.GetThumbnailURL() imagePath := builder.GetImageURL() return &models.ImagePathsType{ diff --git a/pkg/api/resolver_model_movie.go b/pkg/api/resolver_model_movie.go index 137113ed7..afd82ab8a 100644 --- a/pkg/api/resolver_model_movie.go +++ b/pkg/api/resolver_model_movie.go @@ -84,13 +84,13 @@ func (r *movieResolver) Synopsis(ctx context.Context, obj *models.Movie) (*strin func (r *movieResolver) FrontImagePath(ctx context.Context, obj *models.Movie) (*string, error) { baseURL, _ := ctx.Value(BaseURLCtxKey).(string) - frontimagePath := urlbuilders.NewMovieURLBuilder(baseURL, obj.ID).GetMovieFrontImageURL() + frontimagePath := urlbuilders.NewMovieURLBuilder(baseURL, obj).GetMovieFrontImageURL() return &frontimagePath, nil } func (r *movieResolver) BackImagePath(ctx context.Context, obj *models.Movie) (*string, error) { baseURL, _ := ctx.Value(BaseURLCtxKey).(string) - backimagePath := urlbuilders.NewMovieURLBuilder(baseURL, obj.ID).GetMovieBackImageURL() + backimagePath := urlbuilders.NewMovieURLBuilder(baseURL, obj).GetMovieBackImageURL() return &backimagePath, nil } diff --git a/pkg/api/resolver_model_performer.go b/pkg/api/resolver_model_performer.go index 21857d2b7..cef67c22a 100644 --- a/pkg/api/resolver_model_performer.go +++ b/pkg/api/resolver_model_performer.go @@ -134,7 +134,7 @@ func (r *performerResolver) Favorite(ctx context.Context, obj *models.Performer) func (r *performerResolver) ImagePath(ctx context.Context, obj *models.Performer) (*string, error) { baseURL, _ := ctx.Value(BaseURLCtxKey).(string) - imagePath := urlbuilders.NewPerformerURLBuilder(baseURL, obj.ID).GetPerformerImageURL() + imagePath := urlbuilders.NewPerformerURLBuilder(baseURL, obj).GetPerformerImageURL() return &imagePath, nil } diff --git a/pkg/api/resolver_model_studio.go b/pkg/api/resolver_model_studio.go index dac4e265e..1f866b004 100644 --- a/pkg/api/resolver_model_studio.go +++ b/pkg/api/resolver_model_studio.go @@ -23,7 +23,7 @@ func (r *studioResolver) URL(ctx context.Context, obj *models.Studio) (*string, func (r *studioResolver) ImagePath(ctx context.Context, obj *models.Studio) (*string, error) { baseURL, _ := ctx.Value(BaseURLCtxKey).(string) - imagePath := urlbuilders.NewStudioURLBuilder(baseURL, obj.ID).GetStudioImageURL() + imagePath := urlbuilders.NewStudioURLBuilder(baseURL, obj).GetStudioImageURL() var hasImage bool if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error { diff --git a/pkg/api/resolver_model_tag.go b/pkg/api/resolver_model_tag.go index 6e43dac50..1cbb3acf3 100644 --- a/pkg/api/resolver_model_tag.go +++ b/pkg/api/resolver_model_tag.go @@ -45,6 +45,6 @@ func (r *tagResolver) PerformerCount(ctx context.Context, obj *models.Tag) (ret func (r *tagResolver) ImagePath(ctx context.Context, obj *models.Tag) (*string, error) { baseURL, _ := ctx.Value(BaseURLCtxKey).(string) - imagePath := urlbuilders.NewTagURLBuilder(baseURL, obj.ID).GetTagImageURL() + imagePath := urlbuilders.NewTagURLBuilder(baseURL, obj).GetTagImageURL() return &imagePath, nil } diff --git a/pkg/api/urlbuilders/image.go b/pkg/api/urlbuilders/image.go index e81dd446e..9594a4530 100644 --- a/pkg/api/urlbuilders/image.go +++ b/pkg/api/urlbuilders/image.go @@ -1,25 +1,28 @@ package urlbuilders import ( + "github.com/stashapp/stash/pkg/models" "strconv" ) type ImageURLBuilder struct { - BaseURL string - ImageID string + BaseURL string + ImageID string + UpdatedAt string } -func NewImageURLBuilder(baseURL string, imageID int) ImageURLBuilder { +func NewImageURLBuilder(baseURL string, image *models.Image) ImageURLBuilder { return ImageURLBuilder{ - BaseURL: baseURL, - ImageID: strconv.Itoa(imageID), + BaseURL: baseURL, + ImageID: strconv.Itoa(image.ID), + UpdatedAt: strconv.FormatInt(image.UpdatedAt.Timestamp.Unix(), 10), } } func (b ImageURLBuilder) GetImageURL() string { - return b.BaseURL + "/image/" + b.ImageID + "/image" + return b.BaseURL + "/image/" + b.ImageID + "/image?" + b.UpdatedAt } func (b ImageURLBuilder) GetThumbnailURL() string { - return b.BaseURL + "/image/" + b.ImageID + "/thumbnail" + return b.BaseURL + "/image/" + b.ImageID + "/thumbnail?" + b.UpdatedAt } diff --git a/pkg/api/urlbuilders/movie.go b/pkg/api/urlbuilders/movie.go index 6f7694b83..c50536c96 100644 --- a/pkg/api/urlbuilders/movie.go +++ b/pkg/api/urlbuilders/movie.go @@ -1,23 +1,28 @@ package urlbuilders -import "strconv" +import ( + "github.com/stashapp/stash/pkg/models" + "strconv" +) type MovieURLBuilder struct { - BaseURL string - MovieID string + BaseURL string + MovieID string + UpdatedAt string } -func NewMovieURLBuilder(baseURL string, movieID int) MovieURLBuilder { +func NewMovieURLBuilder(baseURL string, movie *models.Movie) MovieURLBuilder { return MovieURLBuilder{ - BaseURL: baseURL, - MovieID: strconv.Itoa(movieID), + BaseURL: baseURL, + MovieID: strconv.Itoa(movie.ID), + UpdatedAt: strconv.FormatInt(movie.UpdatedAt.Timestamp.Unix(), 10), } } func (b MovieURLBuilder) GetMovieFrontImageURL() string { - return b.BaseURL + "/movie/" + b.MovieID + "/frontimage" + return b.BaseURL + "/movie/" + b.MovieID + "/frontimage?" + b.UpdatedAt } func (b MovieURLBuilder) GetMovieBackImageURL() string { - return b.BaseURL + "/movie/" + b.MovieID + "/backimage" + return b.BaseURL + "/movie/" + b.MovieID + "/backimage?" + b.UpdatedAt } diff --git a/pkg/api/urlbuilders/performer.go b/pkg/api/urlbuilders/performer.go index b7c450617..e7e0b2626 100644 --- a/pkg/api/urlbuilders/performer.go +++ b/pkg/api/urlbuilders/performer.go @@ -1,19 +1,24 @@ package urlbuilders -import "strconv" +import ( + "github.com/stashapp/stash/pkg/models" + "strconv" +) type PerformerURLBuilder struct { BaseURL string PerformerID string + UpdatedAt string } -func NewPerformerURLBuilder(baseURL string, performerID int) PerformerURLBuilder { +func NewPerformerURLBuilder(baseURL string, performer *models.Performer) PerformerURLBuilder { return PerformerURLBuilder{ BaseURL: baseURL, - PerformerID: strconv.Itoa(performerID), + PerformerID: strconv.Itoa(performer.ID), + UpdatedAt: strconv.FormatInt(performer.UpdatedAt.Timestamp.Unix(), 10), } } func (b PerformerURLBuilder) GetPerformerImageURL() string { - return b.BaseURL + "/performer/" + b.PerformerID + "/image" + return b.BaseURL + "/performer/" + b.PerformerID + "/image?" + b.UpdatedAt } diff --git a/pkg/api/urlbuilders/studio.go b/pkg/api/urlbuilders/studio.go index eaa909dc4..7713aa5b9 100644 --- a/pkg/api/urlbuilders/studio.go +++ b/pkg/api/urlbuilders/studio.go @@ -1,19 +1,24 @@ package urlbuilders -import "strconv" +import ( + "github.com/stashapp/stash/pkg/models" + "strconv" +) type StudioURLBuilder struct { - BaseURL string - StudioID string + BaseURL string + StudioID string + UpdatedAt string } -func NewStudioURLBuilder(baseURL string, studioID int) StudioURLBuilder { +func NewStudioURLBuilder(baseURL string, studio *models.Studio) StudioURLBuilder { return StudioURLBuilder{ - BaseURL: baseURL, - StudioID: strconv.Itoa(studioID), + BaseURL: baseURL, + StudioID: strconv.Itoa(studio.ID), + UpdatedAt: strconv.FormatInt(studio.UpdatedAt.Timestamp.Unix(), 10), } } func (b StudioURLBuilder) GetStudioImageURL() string { - return b.BaseURL + "/studio/" + b.StudioID + "/image" + return b.BaseURL + "/studio/" + b.StudioID + "/image?" + b.UpdatedAt } diff --git a/pkg/api/urlbuilders/tag.go b/pkg/api/urlbuilders/tag.go index e3f9415c9..a0f5a27dc 100644 --- a/pkg/api/urlbuilders/tag.go +++ b/pkg/api/urlbuilders/tag.go @@ -1,19 +1,24 @@ package urlbuilders -import "strconv" +import ( + "github.com/stashapp/stash/pkg/models" + "strconv" +) type TagURLBuilder struct { - BaseURL string - TagID string + BaseURL string + TagID string + UpdatedAt string } -func NewTagURLBuilder(baseURL string, tagID int) TagURLBuilder { +func NewTagURLBuilder(baseURL string, tag *models.Tag) TagURLBuilder { return TagURLBuilder{ - BaseURL: baseURL, - TagID: strconv.Itoa(tagID), + BaseURL: baseURL, + TagID: strconv.Itoa(tag.ID), + UpdatedAt: strconv.FormatInt(tag.UpdatedAt.Timestamp.Unix(), 10), } } func (b TagURLBuilder) GetTagImageURL() string { - return b.BaseURL + "/tag/" + b.TagID + "/image" + return b.BaseURL + "/tag/" + b.TagID + "/image?" + b.UpdatedAt } diff --git a/pkg/utils/image.go b/pkg/utils/image.go index 7958f1d4e..488e8049a 100644 --- a/pkg/utils/image.go +++ b/pkg/utils/image.go @@ -121,6 +121,7 @@ func ServeImage(image []byte, w http.ResponseWriter, r *http.Request) error { w.Header().Set("Content-Type", contentType) w.Header().Add("Etag", etag) + w.Header().Set("Cache-Control", "public, max-age=604800, immutable") _, err := w.Write(image) return err } diff --git a/ui/v2.5/src/components/Performers/PerformerDetails/PerformerEditPanel.tsx b/ui/v2.5/src/components/Performers/PerformerDetails/PerformerEditPanel.tsx index 25b4a3128..9f670cbb9 100644 --- a/ui/v2.5/src/components/Performers/PerformerDetails/PerformerEditPanel.tsx +++ b/ui/v2.5/src/components/Performers/PerformerDetails/PerformerEditPanel.tsx @@ -326,11 +326,6 @@ export const PerformerEditPanel: React.FC = ({ } as GQL.PerformerUpdateInput, }, }); - if (performerInput.image) { - // Refetch image to bust browser cache - await fetch(`/performer/${performer.id}/image`, { cache: "reload" }); - } - history.push(`/performers/${performer.id}`); } else { const result = await createPerformer({ diff --git a/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx b/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx index 42b7b6119..048f199b3 100644 --- a/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx +++ b/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx @@ -134,10 +134,6 @@ export const Studio: React.FC = () => { input: getStudioInput() as GQL.StudioUpdateInput, }, }); - if (result.data?.studioUpdate?.image_path) - await fetch(result.data?.studioUpdate?.image_path, { - cache: "reload", - }); if (result.data?.studioUpdate) { updateStudioData(result.data.studioUpdate); setIsEditing(false); diff --git a/ui/v2.5/src/components/Tags/TagDetails/Tag.tsx b/ui/v2.5/src/components/Tags/TagDetails/Tag.tsx index 17cfdf467..c1ec1d63f 100644 --- a/ui/v2.5/src/components/Tags/TagDetails/Tag.tsx +++ b/ui/v2.5/src/components/Tags/TagDetails/Tag.tsx @@ -141,8 +141,6 @@ export const Tag: React.FC = () => { }, }); if (result.data?.tagUpdate) { - if (result.data.tagUpdate.image_path) - await fetch(result.data.tagUpdate.image_path, { cache: "reload" }); updateTagData(result.data.tagUpdate); setIsEditing(false); }