Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: thumbnail should show last thumbnail in server in any condition #858

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions internal/http/response/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import (
"github.com/go-shiori/shiori/internal/model"
)

// SendFile sends file to client with caching header
func SendFile(c *gin.Context, storageDomain model.StorageDomain, path string) {
c.Header("Cache-Control", "public, max-age=86400")
type SendFileOptions struct {
Headers []http.Header
}

// SendFile sends file to client with caching header
func SendFile(c *gin.Context, storageDomain model.StorageDomain, path string, options *SendFileOptions) {
if !storageDomain.FileExists(path) {
c.AbortWithStatus(http.StatusNotFound)
return
Expand All @@ -24,8 +26,17 @@ func SendFile(c *gin.Context, storageDomain model.StorageDomain, path string) {
return
}

c.Header("Cache-Control", "public, max-age=86400")
c.Header("ETag", fmt.Sprintf("W/%x-%x", info.ModTime().Unix(), info.Size()))

if options != nil {
for _, header := range options.Headers {
for key, value := range header {
c.Header(key, value[0])
}
}
}

// TODO: Find a better way to send the file to the client from the FS, probably making a
// conversion between afero.Fs and http.FileSystem to use c.FileFromFS.
fileContent, err := storageDomain.FS().Open(path)
Expand Down
20 changes: 18 additions & 2 deletions internal/http/routes/bookmark.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,23 @@ func (r *BookmarkRoutes) bookmarkThumbnailHandler(c *gin.Context) {
return
}

response.SendFile(c, r.deps.Domains.Storage, model.GetThumbnailPath(bookmark))
etag := "w/" + model.GetThumbnailPath(bookmark) + "-" + bookmark.ModifiedAt

// Check if the client's ETag matches the current ETag
if c.GetHeader("If-None-Match") == etag {
c.Status(http.StatusNotModified)
return
}

options := &response.SendFileOptions{
Headers: []http.Header{
{"Cache-Control": {"no-cache , must-revalidate"}},
{"Last-Modified": {bookmark.ModifiedAt}},
{"ETag": {etag}},
},
}

response.SendFile(c, r.deps.Domains.Storage, model.GetThumbnailPath(bookmark), options)
}

func (r *BookmarkRoutes) bookmarkEbookHandler(c *gin.Context) {
Expand All @@ -185,5 +201,5 @@ func (r *BookmarkRoutes) bookmarkEbookHandler(c *gin.Context) {

// TODO: Potentially improve this
c.Header("Content-Disposition", `attachment; filename="`+bookmark.Title+`.epub"`)
response.SendFile(c, r.deps.Domains.Storage, model.GetEbookPath(bookmark))
response.SendFile(c, r.deps.Domains.Storage, model.GetEbookPath(bookmark), nil)
}
3 changes: 2 additions & 1 deletion internal/view/assets/js/component/bookmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default {
hasContent: Boolean,
hasArchive: Boolean,
hasEbook: Boolean,
modifiedAt: String,
index: Number,
ShowId: Boolean,
editMode: Boolean,
Expand Down Expand Up @@ -95,7 +96,7 @@ export default {
},
thumbnailStyleURL() {
return {
backgroundImage: `url("${this.imageURL}")`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use some properties from the bookmark instead of a random string? This could break the cache unintentially since each time the query string is going to be different. Can we use ?mtime=<bookmark modified time> ?

Copy link
Collaborator Author

@Monirzadeh Monirzadeh Mar 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will modified time update if just thumbnail update in article? i am sure that i am not update that in #683 so if that will handle in other part of code automatically we can use modified time too.
i don't find when modified time update in code. do you know where is that or i can send request to update that while thumbnail update

if just thumbnail will update but modify time not update automatically than it will get in trouble in that situation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always assumed Bookmark.ModifiedTime was the datetime when the bookmark was last modified (attributes/archive/readable/ebook) modified, it seems that is not the case. Let me think and get back to you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up not updating you here.

My idea is:

  • Refactor the migration system (feat: new migration system #876)
  • Add a created column to the bookmarks with the time the bookmark was first created and prefill it with the current modified for existing bookmarks.
  • Update modified every time the bookmark is updated (either the data, content, archive, etc).

Then, we can use the modified as query parameter for the thumbnail.

Copy link
Collaborator Author

@Monirzadeh Monirzadeh Apr 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is better so i will wait until #876 finish than start working on that.
but an small point: i like the idea of keep first created time and modified time separately if exist instead of prefill (you can look at #848)
so created and modified be better to separated. having created time help me to track my activity in long term so i think having that can be helpful.
@fmartingr and @GreenBlast what do you think?

Copy link
Collaborator Author

@Monirzadeh Monirzadeh Apr 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you mention the function that currently update modified time? i can't find that (to use when just thumbnail update).

backgroundImage: `url("${this.imageURL}?modifiedAt=${this.modifiedAt}")`,
};
},
eventItem() {
Expand Down
1 change: 1 addition & 0 deletions internal/view/assets/js/page/home.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ var template = `
:excerpt="book.excerpt"
:public="book.public"
:imageURL="book.imageURL"
:modifiedAt="book.modifiedAt"
:hasContent="book.hasContent"
:hasArchive="book.hasArchive"
:hasEbook="book.hasEbook"
Expand Down
Loading