Skip to content

Commit 37c2ad6

Browse files
committed
Merge pull request gregjones#49 from gregjones/dont-store-uncacheable-method-responses
Fix invalid caching of uncacheable methods.
2 parents 2f25d93 + 81de9c4 commit 37c2ad6

File tree

2 files changed

+70
-6
lines changed

2 files changed

+70
-6
lines changed

‎httpcache.go‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,7 @@ func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error
281281
}
282282
}
283283

284-
reqCacheControl := parseCacheControl(req.Header)
285-
respCacheControl := parseCacheControl(resp.Header)
286-
287-
if canStore(reqCacheControl, respCacheControl) {
284+
if cacheableMethod && canStore(parseCacheControl(req.Header), parseCacheControl(resp.Header)) {
288285
for _, varyKey := range headerAllCommaSepValues(resp.Header, "vary") {
289286
varyKey = http.CanonicalHeaderKey(varyKey)
290287
fakeHeader := "X-Varied-" + varyKey

‎httpcache_test.go‎

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"errors"
66
"flag"
7+
"io"
78
"io/ioutil"
89
"net/http"
910
"net/http/httptest"
@@ -48,6 +49,11 @@ func setup() {
4849
w.Header().Set("Cache-Control", "max-age=3600")
4950
}))
5051

52+
mux.HandleFunc("/method", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
53+
w.Header().Set("Cache-Control", "max-age=3600")
54+
w.Write([]byte(r.Method))
55+
}))
56+
5157
mux.HandleFunc("/nostore", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
5258
w.Header().Set("Cache-Control", "no-store")
5359
}))
@@ -56,6 +62,7 @@ func setup() {
5662
etag := "124567"
5763
if r.Header.Get("if-none-match") == etag {
5864
w.WriteHeader(http.StatusNotModified)
65+
return
5966
}
6067
w.Header().Set("etag", etag)
6168
}))
@@ -64,6 +71,7 @@ func setup() {
6471
lm := "Fri, 14 Dec 2010 01:01:50 GMT"
6572
if r.Header.Get("if-modified-since") == lm {
6673
w.WriteHeader(http.StatusNotModified)
74+
return
6775
}
6876
w.Header().Set("last-modified", lm)
6977
}))
@@ -102,9 +110,9 @@ func setup() {
102110
updateFieldsCounter++
103111
if r.Header.Get("if-none-match") != "" {
104112
w.WriteHeader(http.StatusNotModified)
105-
} else {
106-
w.Write([]byte("Some text content"))
113+
return
107114
}
115+
w.Write([]byte("Some text content"))
108116
}))
109117
}
110118

@@ -117,6 +125,65 @@ func resetTest() {
117125
clock = &realClock{}
118126
}
119127

128+
// TestCacheableMethod ensures that uncacheable method does not get stored
129+
// in cache and get incorrectly used for a following cacheable method request.
130+
func TestCacheableMethod(t *testing.T) {
131+
resetTest()
132+
{
133+
req, err := http.NewRequest("POST", s.server.URL+"/method", nil)
134+
if err != nil {
135+
t.Fatal(err)
136+
}
137+
resp, err := s.client.Do(req)
138+
if err != nil {
139+
t.Fatal(err)
140+
}
141+
var buf bytes.Buffer
142+
_, err = io.Copy(&buf, resp.Body)
143+
if err != nil {
144+
t.Fatal(err)
145+
}
146+
err = resp.Body.Close()
147+
if err != nil {
148+
t.Fatal(err)
149+
}
150+
if got, want := buf.String(), "POST"; got != want {
151+
t.Errorf("got %q, want %q", got, want)
152+
}
153+
if resp.StatusCode != http.StatusOK {
154+
t.Errorf("response status code isn't 200 OK: %v", resp.StatusCode)
155+
}
156+
}
157+
{
158+
req, err := http.NewRequest("GET", s.server.URL+"/method", nil)
159+
if err != nil {
160+
t.Fatal(err)
161+
}
162+
resp, err := s.client.Do(req)
163+
if err != nil {
164+
t.Fatal(err)
165+
}
166+
var buf bytes.Buffer
167+
_, err = io.Copy(&buf, resp.Body)
168+
if err != nil {
169+
t.Fatal(err)
170+
}
171+
err = resp.Body.Close()
172+
if err != nil {
173+
t.Fatal(err)
174+
}
175+
if got, want := buf.String(), "GET"; got != want {
176+
t.Errorf("got wrong body %q, want %q", got, want)
177+
}
178+
if resp.StatusCode != http.StatusOK {
179+
t.Errorf("response status code isn't 200 OK: %v", resp.StatusCode)
180+
}
181+
if resp.Header.Get(XFromCache) != "" {
182+
t.Errorf("XFromCache header isn't blank")
183+
}
184+
}
185+
}
186+
120187
func TestGetOnlyIfCachedHit(t *testing.T) {
121188
resetTest()
122189
{

0 commit comments

Comments
 (0)