Skip to content
This repository was archived by the owner on Apr 20, 2023. It is now read-only.

Commit ff2042c

Browse files
committed
Add AroundRoundTrip option, trim the API
1 parent 10eb476 commit ff2042c

File tree

2 files changed

+39
-38
lines changed

2 files changed

+39
-38
lines changed

‎httpcache.go‎

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ func cacheKey(req *http.Request) string {
4545
}
4646
}
4747

48-
// CachedResponse returns the cached http.Response for req if present, and nil
48+
// cachedResponse returns the cached http.Response for req if present, and nil
4949
// otherwise.
50-
func CachedResponse(c Cache, req *http.Request) (resp *http.Response, err error) {
50+
func cachedResponse(c Cache, req *http.Request) (resp *http.Response, err error) {
5151
cachedVal, ok := c.Get(cacheKey(req))
5252
if !ok {
5353
return
@@ -57,37 +57,37 @@ func CachedResponse(c Cache, req *http.Request) (resp *http.Response, err error)
5757
return http.ReadResponse(bufio.NewReader(b), req)
5858
}
5959

60-
// MemoryCache is an implemtation of Cache that stores responses in an in-memory map.
61-
type MemoryCache struct {
60+
// memoryCache is an implemtation of Cache that stores responses in an in-memory map.
61+
type memoryCache struct {
6262
mu sync.RWMutex
6363
items map[string][]byte
6464
}
6565

6666
// Get returns the []byte representation of the response and true if present, false if not
67-
func (c *MemoryCache) Get(key string) (resp []byte, ok bool) {
67+
func (c *memoryCache) Get(key string) (resp []byte, ok bool) {
6868
c.mu.RLock()
6969
resp, ok = c.items[key]
7070
c.mu.RUnlock()
7171
return resp, ok
7272
}
7373

7474
// Set saves response resp to the cache with key
75-
func (c *MemoryCache) Set(key string, resp []byte) {
75+
func (c *memoryCache) Set(key string, resp []byte) {
7676
c.mu.Lock()
7777
c.items[key] = resp
7878
c.mu.Unlock()
7979
}
8080

8181
// Delete removes key from the cache
82-
func (c *MemoryCache) Delete(key string) {
82+
func (c *memoryCache) Delete(key string) {
8383
c.mu.Lock()
8484
delete(c.items, key)
8585
c.mu.Unlock()
8686
}
8787

88-
// NewMemoryCache returns a new Cache that will store items in an in-memory map
89-
func NewMemoryCache() *MemoryCache {
90-
c := &MemoryCache{items: map[string][]byte{}}
88+
// newMemoryCache returns a new Cache that will store items in an in-memory map
89+
func newMemoryCache() *memoryCache {
90+
c := &memoryCache{items: map[string][]byte{}}
9191
return c
9292
}
9393

@@ -98,20 +98,18 @@ type Transport struct {
9898
// The RoundTripper interface actually used to make requests
9999
// If nil, http.DefaultTransport is used
100100
Transport http.RoundTripper
101-
Cache Cache
101+
102+
// The Cache interface used to store and retrieve responses.
103+
Cache Cache
104+
102105
// If true, responses returned from the cache will be given an extra header, X-From-Cache
103106
MarkCachedResponses bool
104-
}
105107

106-
// NewTransport returns a new Transport with the
107-
// provided Cache implementation and MarkCachedResponses set to true
108-
func NewTransport(c Cache) *Transport {
109-
return &Transport{Cache: c, MarkCachedResponses: true}
110-
}
111-
112-
// Client returns an *http.Client that caches responses.
113-
func (t *Transport) Client() *http.Client {
114-
return &http.Client{Transport: t}
108+
// AroundRoundTrip is an optional func.
109+
// If set, the Transport will call AroundRoundTrip at the start of RoundTrip
110+
// and defer the returned func until the end of RoundTrip.
111+
// Typically used to implement a lock that is held for the duration of the RoundTrip.
112+
AroundRoundTrip func(key string) func()
115113
}
116114

117115
// varyMatches will return false unless all of the cached values for the headers listed in Vary
@@ -136,10 +134,13 @@ func varyMatches(cachedResp *http.Response, req *http.Request) bool {
136134
// will be returned.
137135
func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
138136
cacheKey := cacheKey(req)
137+
if f := t.AroundRoundTrip; f != nil {
138+
defer f(cacheKey)()
139+
}
139140
cacheable := (req.Method == "GET" || req.Method == "HEAD") && req.Header.Get("range") == ""
140141
var cachedResp *http.Response
141142
if cacheable {
142-
cachedResp, err = CachedResponse(t.Cache, req)
143+
cachedResp, err = cachedResponse(t.Cache, req)
143144
} else {
144145
// Need to invalidate an existing value
145146
t.Cache.Delete(cacheKey)
@@ -254,8 +255,8 @@ func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error
254255
// ErrNoDateHeader indicates that the HTTP headers contained no Date header.
255256
var ErrNoDateHeader = errors.New("no Date header")
256257

257-
// Date parses and returns the value of the Date header.
258-
func Date(respHeaders http.Header) (date time.Time, err error) {
258+
// date parses and returns the value of the date header.
259+
func date(respHeaders http.Header) (date time.Time, err error) {
259260
dateHeader := respHeaders.Get("date")
260261
if dateHeader == "" {
261262
err = ErrNoDateHeader
@@ -299,7 +300,7 @@ func getFreshness(respHeaders, reqHeaders http.Header) (freshness int) {
299300
return fresh
300301
}
301302

302-
date, err := Date(respHeaders)
303+
date, err := date(respHeaders)
303304
if err != nil {
304305
return stale
305306
}
@@ -398,7 +399,7 @@ func canStaleOnError(respHeaders, reqHeaders http.Header) bool {
398399
}
399400

400401
if lifetime >= 0 {
401-
date, err := Date(respHeaders)
402+
date, err := date(respHeaders)
402403
if err != nil {
403404
return false
404405
}
@@ -541,9 +542,9 @@ func (r *cachingReadCloser) Close() error {
541542
return r.R.Close()
542543
}
543544

544-
// NewMemoryCacheTransport returns a new Transport using the in-memory cache implementation
545-
func NewMemoryCacheTransport() *Transport {
546-
c := NewMemoryCache()
547-
t := NewTransport(c)
545+
// newMemoryCacheTransport returns a new Transport using the in-memory cache implementation
546+
func newMemoryCacheTransport() *Transport {
547+
c := newMemoryCache()
548+
t := &Transport{Cache: c, MarkCachedResponses: true}
548549
return t
549550
}

‎httpcache_test.go‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func TestMain(m *testing.M) {
3737
}
3838

3939
func setup() {
40-
tp := NewMemoryCacheTransport()
40+
tp := newMemoryCacheTransport()
4141
client := http.Client{Transport: tp}
4242
s.transport = tp
4343
s.client = client
@@ -165,7 +165,7 @@ func teardown() {
165165
}
166166

167167
func resetTest() {
168-
s.transport.Cache = NewMemoryCache()
168+
s.transport.Cache = newMemoryCache()
169169
clock = &realClock{}
170170
}
171171

@@ -1206,7 +1206,7 @@ func TestStaleIfErrorRequest(t *testing.T) {
12061206
},
12071207
err: nil,
12081208
}
1209-
tp := NewMemoryCacheTransport()
1209+
tp := newMemoryCacheTransport()
12101210
tp.Transport = &tmock
12111211

12121212
// First time, response is cached on success
@@ -1251,7 +1251,7 @@ func TestStaleIfErrorRequestLifetime(t *testing.T) {
12511251
},
12521252
err: nil,
12531253
}
1254-
tp := NewMemoryCacheTransport()
1254+
tp := newMemoryCacheTransport()
12551255
tp.Transport = &tmock
12561256

12571257
// First time, response is cached on success
@@ -1314,7 +1314,7 @@ func TestStaleIfErrorResponse(t *testing.T) {
13141314
},
13151315
err: nil,
13161316
}
1317-
tp := NewMemoryCacheTransport()
1317+
tp := newMemoryCacheTransport()
13181318
tp.Transport = &tmock
13191319

13201320
// First time, response is cached on success
@@ -1358,7 +1358,7 @@ func TestStaleIfErrorResponseLifetime(t *testing.T) {
13581358
},
13591359
err: nil,
13601360
}
1361-
tp := NewMemoryCacheTransport()
1361+
tp := newMemoryCacheTransport()
13621362
tp.Transport = &tmock
13631363

13641364
// First time, response is cached on success
@@ -1412,7 +1412,7 @@ func TestStaleIfErrorKeepsStatus(t *testing.T) {
14121412
},
14131413
err: nil,
14141414
}
1415-
tp := NewMemoryCacheTransport()
1415+
tp := newMemoryCacheTransport()
14161416
tp.Transport = &tmock
14171417

14181418
// First time, response is cached on success
@@ -1456,7 +1456,7 @@ func TestClientTimeout(t *testing.T) {
14561456
}
14571457
resetTest()
14581458
client := &http.Client{
1459-
Transport: NewMemoryCacheTransport(),
1459+
Transport: newMemoryCacheTransport(),
14601460
Timeout: time.Second,
14611461
}
14621462
started := time.Now()

0 commit comments

Comments
 (0)