Skip to content

Commit fd45e69

Browse files
committed
Set the LastModified header for raw files
Although the use of LastModified dates for caching of git objects should be discouraged (as it is not native to git - and there are a LOT of ways this could be incorrect) - LastModified dates can be a helpful somewhat more human way of caching for simple cases. This PR adds this header and handles the If-Modified-Since header to the /raw/ routes. Fix go-gitea#18354 Signed-off-by: Andrew Thornton <art27@cantab.net>
1 parent 108f1aa commit fd45e69

File tree

2 files changed

+49
-18
lines changed

2 files changed

+49
-18
lines changed

modules/httpcache/httpcache.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,23 @@ func generateETag(fi os.FileInfo) string {
3737

3838
// HandleTimeCache handles time-based caching for a HTTP request
3939
func HandleTimeCache(req *http.Request, w http.ResponseWriter, fi os.FileInfo) (handled bool) {
40+
return HandleGenericTimeCache(req, w, fi.ModTime())
41+
}
42+
43+
// HandleGenericTimeCache handles time-based caching for a HTTP request
44+
func HandleGenericTimeCache(req *http.Request, w http.ResponseWriter, lastModified time.Time) (handled bool) {
4045
AddCacheControlToHeader(w.Header(), setting.StaticCacheTime)
4146

4247
ifModifiedSince := req.Header.Get("If-Modified-Since")
4348
if ifModifiedSince != "" {
4449
t, err := time.Parse(http.TimeFormat, ifModifiedSince)
45-
if err == nil && fi.ModTime().Unix() <= t.Unix() {
50+
if err == nil && lastModified.Unix() <= t.Unix() {
4651
w.WriteHeader(http.StatusNotModified)
4752
return true
4853
}
4954
}
5055

51-
w.Header().Set("Last-Modified", fi.ModTime().Format(http.TimeFormat))
56+
w.Header().Set("Last-Modified", lastModified.Format(http.TimeFormat))
5257
return false
5358
}
5459

routers/web/repo/download.go

+42-16
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
package repo
77

88
import (
9+
"path"
10+
911
"code.gitea.io/gitea/models"
12+
"code.gitea.io/gitea/modules/cache"
1013
"code.gitea.io/gitea/modules/context"
1114
"code.gitea.io/gitea/modules/git"
1215
"code.gitea.io/gitea/modules/httpcache"
@@ -79,34 +82,57 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
7982
return common.ServeBlob(ctx, blob)
8083
}
8184

85+
func getBlobForEntry(ctx *context.Context) *git.Blob {
86+
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
87+
if err != nil {
88+
ctx.ServerError("GetBlobByPath", err)
89+
return nil
90+
}
91+
92+
if entry.IsDir() || entry.IsSubModule() {
93+
ctx.NotFound("GetBlobByPath", nil)
94+
return nil
95+
}
96+
97+
var c *git.LastCommitCache
98+
if setting.CacheService.LastCommit.Enabled && ctx.Repo.CommitsCount >= setting.CacheService.LastCommit.CommitsCount {
99+
c = git.NewLastCommitCache(ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, setting.LastCommitCacheTTLSeconds, cache.GetCache())
100+
}
101+
102+
info, _, err := git.Entries([]*git.TreeEntry{entry}).GetCommitsInfo(ctx, ctx.Repo.Commit, path.Dir("/" + ctx.Repo.TreePath)[1:], c)
103+
if err != nil {
104+
ctx.ServerError("GetCommitsInfo", err)
105+
return nil
106+
}
107+
108+
if len(info) == 1 && httpcache.HandleGenericTimeCache(ctx.Req, ctx.Resp, info[0].Commit.Committer.When) {
109+
// Not Modified
110+
return nil
111+
}
112+
113+
return entry.Blob()
114+
}
115+
82116
// SingleDownload download a file by repos path
83117
func SingleDownload(ctx *context.Context) {
84-
blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreePath)
85-
if err != nil {
86-
if git.IsErrNotExist(err) {
87-
ctx.NotFound("GetBlobByPath", nil)
88-
} else {
89-
ctx.ServerError("GetBlobByPath", err)
90-
}
118+
blob := getBlobForEntry(ctx)
119+
if blob == nil {
91120
return
92121
}
93-
if err = common.ServeBlob(ctx, blob); err != nil {
122+
123+
if err := common.ServeBlob(ctx, blob); err != nil {
94124
ctx.ServerError("ServeBlob", err)
95125
}
96126
}
97127

98128
// SingleDownloadOrLFS download a file by repos path redirecting to LFS if necessary
99129
func SingleDownloadOrLFS(ctx *context.Context) {
100-
blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreePath)
101-
if err != nil {
102-
if git.IsErrNotExist(err) {
103-
ctx.NotFound("GetBlobByPath", nil)
104-
} else {
105-
ctx.ServerError("GetBlobByPath", err)
106-
}
130+
blob := getBlobForEntry(ctx)
131+
if blob == nil {
107132
return
108133
}
109-
if err = ServeBlobOrLFS(ctx, blob); err != nil {
134+
135+
if err := ServeBlobOrLFS(ctx, blob); err != nil {
110136
ctx.ServerError("ServeBlobOrLFS", err)
111137
}
112138
}

0 commit comments

Comments
 (0)