Skip to content

Commit 2257fab

Browse files
committed
fix
1 parent f745016 commit 2257fab

File tree

8 files changed

+22
-157
lines changed

8 files changed

+22
-157
lines changed

Diff for: modules/context/context_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ package context
55

66
import (
77
"net/http"
8+
"net/http/httptest"
89
"testing"
910

10-
"code.gitea.io/gitea/modules/httplib"
1111
"code.gitea.io/gitea/modules/setting"
1212

1313
"github.com/stretchr/testify/assert"
1414
)
1515

1616
func TestRemoveSessionCookieHeader(t *testing.T) {
17-
w := httplib.NewMockResponseWriter()
17+
w := httptest.NewRecorder()
1818
w.Header().Add("Set-Cookie", (&http.Cookie{Name: setting.SessionConfig.CookieName, Value: "foo"}).String())
1919
w.Header().Add("Set-Cookie", (&http.Cookie{Name: "other", Value: "bar"}).String())
2020
assert.Len(t, w.Header().Values("Set-Cookie"), 2)

Diff for: modules/httpcache/httpcache.go

+3-34
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
package httpcache
55

66
import (
7-
"encoding/base64"
8-
"fmt"
7+
"io"
98
"net/http"
10-
"os"
119
"strconv"
1210
"strings"
1311
"time"
@@ -37,38 +35,9 @@ func SetCacheControlInHeader(h http.Header, maxAge time.Duration, additionalDire
3735
h.Set("Cache-Control", strings.Join(append(directives, additionalDirectives...), ", "))
3836
}
3937

40-
// generateETag generates an ETag based on size, filename and file modification time
41-
func generateETag(fi os.FileInfo) string {
42-
etag := fmt.Sprint(fi.Size()) + fi.Name() + fi.ModTime().UTC().Format(http.TimeFormat)
43-
return `"` + base64.StdEncoding.EncodeToString([]byte(etag)) + `"`
44-
}
45-
46-
// HandleTimeCache handles time-based caching for a HTTP request
47-
func HandleTimeCache(req *http.Request, w http.ResponseWriter, fi os.FileInfo) (handled bool) {
48-
return HandleGenericTimeCache(req, w, fi.ModTime())
49-
}
50-
51-
// HandleGenericTimeCache handles time-based caching for a HTTP request
52-
func HandleGenericTimeCache(req *http.Request, w http.ResponseWriter, lastModified time.Time) (handled bool) {
38+
func ServeContentWithCacheControl(w http.ResponseWriter, req *http.Request, name string, modTime time.Time, content io.ReadSeeker) {
5339
SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
54-
55-
ifModifiedSince := req.Header.Get("If-Modified-Since")
56-
if ifModifiedSince != "" {
57-
t, err := time.Parse(http.TimeFormat, ifModifiedSince)
58-
if err == nil && lastModified.Unix() <= t.Unix() {
59-
w.WriteHeader(http.StatusNotModified)
60-
return true
61-
}
62-
}
63-
64-
w.Header().Set("Last-Modified", lastModified.Format(http.TimeFormat))
65-
return false
66-
}
67-
68-
// HandleFileETagCache handles ETag-based caching for a HTTP request
69-
func HandleFileETagCache(req *http.Request, w http.ResponseWriter, fi os.FileInfo) (handled bool) {
70-
etag := generateETag(fi)
71-
return HandleGenericETagCache(req, w, etag)
40+
http.ServeContent(w, req, name, modTime, content)
7241
}
7342

7443
// HandleGenericETagCache handles ETag-based caching for a HTTP request.

Diff for: modules/httpcache/httpcache_test.go

-57
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,12 @@ package httpcache
66
import (
77
"net/http"
88
"net/http/httptest"
9-
"os"
109
"strings"
1110
"testing"
12-
"time"
1311

1412
"github.com/stretchr/testify/assert"
1513
)
1614

17-
type mockFileInfo struct{}
18-
19-
func (m mockFileInfo) Name() string { return "gitea.test" }
20-
func (m mockFileInfo) Size() int64 { return int64(10) }
21-
func (m mockFileInfo) Mode() os.FileMode { return os.ModePerm }
22-
func (m mockFileInfo) ModTime() time.Time { return time.Time{} }
23-
func (m mockFileInfo) IsDir() bool { return false }
24-
func (m mockFileInfo) Sys() interface{} { return nil }
25-
2615
func countFormalHeaders(h http.Header) (c int) {
2716
for k := range h {
2817
// ignore our headers for internal usage
@@ -34,52 +23,6 @@ func countFormalHeaders(h http.Header) (c int) {
3423
return c
3524
}
3625

37-
func TestHandleFileETagCache(t *testing.T) {
38-
fi := mockFileInfo{}
39-
etag := `"MTBnaXRlYS50ZXN0TW9uLCAwMSBKYW4gMDAwMSAwMDowMDowMCBHTVQ="`
40-
41-
t.Run("No_If-None-Match", func(t *testing.T) {
42-
req := &http.Request{Header: make(http.Header)}
43-
w := httptest.NewRecorder()
44-
45-
handled := HandleFileETagCache(req, w, fi)
46-
47-
assert.False(t, handled)
48-
assert.Equal(t, 2, countFormalHeaders(w.Header()))
49-
assert.Contains(t, w.Header(), "Cache-Control")
50-
assert.Contains(t, w.Header(), "Etag")
51-
assert.Equal(t, etag, w.Header().Get("Etag"))
52-
})
53-
t.Run("Wrong_If-None-Match", func(t *testing.T) {
54-
req := &http.Request{Header: make(http.Header)}
55-
w := httptest.NewRecorder()
56-
57-
req.Header.Set("If-None-Match", `"wrong etag"`)
58-
59-
handled := HandleFileETagCache(req, w, fi)
60-
61-
assert.False(t, handled)
62-
assert.Equal(t, 2, countFormalHeaders(w.Header()))
63-
assert.Contains(t, w.Header(), "Cache-Control")
64-
assert.Contains(t, w.Header(), "Etag")
65-
assert.Equal(t, etag, w.Header().Get("Etag"))
66-
})
67-
t.Run("Correct_If-None-Match", func(t *testing.T) {
68-
req := &http.Request{Header: make(http.Header)}
69-
w := httptest.NewRecorder()
70-
71-
req.Header.Set("If-None-Match", etag)
72-
73-
handled := HandleFileETagCache(req, w, fi)
74-
75-
assert.True(t, handled)
76-
assert.Equal(t, 1, countFormalHeaders(w.Header()))
77-
assert.Contains(t, w.Header(), "Etag")
78-
assert.Equal(t, etag, w.Header().Get("Etag"))
79-
assert.Equal(t, http.StatusNotModified, w.Code)
80-
})
81-
}
82-
8326
func TestHandleGenericETagCache(t *testing.T) {
8427
etag := `"test"`
8528

Diff for: modules/httplib/mock.go

-35
This file was deleted.

Diff for: modules/httplib/serve_test.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package httplib
66
import (
77
"fmt"
88
"net/http"
9+
"net/http/httptest"
910
"net/url"
1011
"os"
1112
"strings"
@@ -25,12 +26,12 @@ func TestServeContentByReader(t *testing.T) {
2526
r.Header.Set("Range", fmt.Sprintf("bytes=%s", rangeStr))
2627
}
2728
reader := strings.NewReader(data)
28-
w := NewMockResponseWriter()
29+
w := httptest.NewRecorder()
2930
ServeContentByReader(r, w, "test", int64(len(data)), reader)
30-
assert.Equal(t, expectedStatusCode, w.StatusCode)
31+
assert.Equal(t, expectedStatusCode, w.Code)
3132
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
3233
assert.Equal(t, fmt.Sprint(len(expectedContent)), w.Header().Get("Content-Length"))
33-
assert.Equal(t, expectedContent, w.BodyBuffer.String())
34+
assert.Equal(t, expectedContent, w.Body.String())
3435
}
3536
}
3637

@@ -76,12 +77,12 @@ func TestServeContentByReadSeeker(t *testing.T) {
7677
}
7778
defer seekReader.Close()
7879

79-
w := NewMockResponseWriter()
80+
w := httptest.NewRecorder()
8081
ServeContentByReadSeeker(r, w, "test", time.Time{}, seekReader)
81-
assert.Equal(t, expectedStatusCode, w.StatusCode)
82+
assert.Equal(t, expectedStatusCode, w.Code)
8283
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
8384
assert.Equal(t, fmt.Sprint(len(expectedContent)), w.Header().Get("Content-Length"))
84-
assert.Equal(t, expectedContent, w.BodyBuffer.String())
85+
assert.Equal(t, expectedContent, w.Body.String())
8586
}
8687
}
8788

Diff for: modules/public/public.go

+2-6
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,6 @@ func handleRequest(w http.ResponseWriter, req *http.Request, fs http.FileSystem,
9797
return true
9898
}
9999

100-
if httpcache.HandleFileETagCache(req, w, fi) {
101-
return true
102-
}
103-
104100
serveContent(w, req, fi, fi.ModTime(), f)
105101
return true
106102
}
@@ -124,11 +120,11 @@ func serveContent(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modt
124120
w.Header().Set("Content-Type", "application/octet-stream")
125121
}
126122
w.Header().Set("Content-Encoding", "gzip")
127-
http.ServeContent(w, req, fi.Name(), modtime, rdGzip)
123+
httpcache.ServeContentWithCacheControl(w, req, fi.Name(), modtime, rdGzip)
128124
return
129125
}
130126
}
131127

132-
http.ServeContent(w, req, fi.Name(), modtime, content)
128+
httpcache.ServeContentWithCacheControl(w, req, fi.Name(), modtime, content)
133129
return
134130
}

Diff for: routers/web/base.go

+5-11
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package web
66
import (
77
"errors"
88
"fmt"
9-
"io"
109
"net/http"
1110
"os"
1211
"path"
@@ -76,12 +75,6 @@ func storageHandler(storageSetting setting.Storage, prefix string, objStore stor
7675
}
7776

7877
fi, err := objStore.Stat(rPath)
79-
if err == nil && httpcache.HandleTimeCache(req, w, fi) {
80-
return
81-
}
82-
83-
// If we have matched and access to release or issue
84-
fr, err := objStore.Open(rPath)
8578
if err != nil {
8679
if os.IsNotExist(err) || errors.Is(err, os.ErrNotExist) {
8780
log.Warn("Unable to find %s %s", prefix, rPath)
@@ -92,14 +85,15 @@ func storageHandler(storageSetting setting.Storage, prefix string, objStore stor
9285
http.Error(w, fmt.Sprintf("Error whilst opening %s %s", prefix, rPath), http.StatusInternalServerError)
9386
return
9487
}
95-
defer fr.Close()
9688

97-
_, err = io.Copy(w, fr)
89+
fr, err := objStore.Open(rPath)
9890
if err != nil {
99-
log.Error("Error whilst rendering %s %s. Error: %v", prefix, rPath, err)
100-
http.Error(w, fmt.Sprintf("Error whilst rendering %s %s", prefix, rPath), http.StatusInternalServerError)
91+
log.Error("Error whilst opening %s %s. Error: %v", prefix, rPath, err)
92+
http.Error(w, fmt.Sprintf("Error whilst opening %s %s", prefix, rPath), http.StatusInternalServerError)
10193
return
10294
}
95+
defer fr.Close()
96+
httpcache.ServeContentWithCacheControl(w, req, path.Base(rPath), fi.ModTime(), fr)
10397
})
10498
}
10599
}

Diff for: routers/web/misc/misc.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ package misc
55

66
import (
77
"net/http"
8-
"os"
98
"path"
109

1110
"code.gitea.io/gitea/modules/git"
1211
"code.gitea.io/gitea/modules/httpcache"
1312
"code.gitea.io/gitea/modules/log"
1413
"code.gitea.io/gitea/modules/setting"
14+
"code.gitea.io/gitea/modules/util"
1515
)
1616

1717
func SSHInfo(rw http.ResponseWriter, req *http.Request) {
@@ -34,11 +34,8 @@ func DummyOK(w http.ResponseWriter, req *http.Request) {
3434
}
3535

3636
func RobotsTxt(w http.ResponseWriter, req *http.Request) {
37-
filePath := path.Join(setting.CustomPath, "robots.txt")
38-
fi, err := os.Stat(filePath)
39-
if err == nil && httpcache.HandleTimeCache(req, w, fi) {
40-
return
41-
}
37+
filePath := util.FilePathJoinAbs(setting.CustomPath, "robots.txt")
38+
httpcache.SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
4239
http.ServeFile(w, req, filePath)
4340
}
4441

0 commit comments

Comments
 (0)