Skip to content

Commit

Permalink
Make response varies on multi-value header cacheable
Browse files Browse the repository at this point in the history
This resulted in actions-runner-controller to not cache API responses when one used GitHub App authentication, because in the current version of go-github, the client sets

"Accept":["application/vnd.github.v3+json","application/vnd.github.machine-man-preview+json"]

and httpcache produces X-Varied-Accept:

"X-Varied-Accept":["application/vnd.github.v3+json"]

`varyMatches` thinks they do not match.

With this patch, the produced X-Varied-Accept becomes:

"X-Varied-Accept":["application/vnd.github.v3+json"]

and that fixes the issue.
  • Loading branch information
mumoshu committed Mar 12, 2022
1 parent 901d907 commit 70d975e
Showing 1 changed file with 19 additions and 4 deletions.
23 changes: 19 additions & 4 deletions httpcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,27 @@ func (t *Transport) Client() *http.Client {
func varyMatches(cachedResp *http.Response, req *http.Request) bool {
for _, header := range headerAllCommaSepValues(cachedResp.Header, "vary") {
header = http.CanonicalHeaderKey(header)
if header != "" && req.Header.Get(header) != cachedResp.Header.Get("X-Varied-"+header) {
if header != "" && !matchValues(req.Header.Values(header), cachedResp.Header.Values("X-Varied-"+header)) {
return false
}
}
return true
}

func matchValues(l, r []string) bool {
if len(l) != len(r) {
return false
}

for i, l := range l {
if l != r[i] {
return false
}
}

return true
}

// RoundTrip takes a Request and returns a Response
//
// If there is a fresh Response already in cache, then it will be returned without connecting to
Expand Down Expand Up @@ -222,9 +236,10 @@ func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error
for _, varyKey := range headerAllCommaSepValues(resp.Header, "vary") {
varyKey = http.CanonicalHeaderKey(varyKey)
fakeHeader := "X-Varied-" + varyKey
reqValue := req.Header.Get(varyKey)
if reqValue != "" {
resp.Header.Set(fakeHeader, reqValue)
reqValues := req.Header.Values(varyKey)
resp.Header.Del(fakeHeader)
for _, v := range reqValues {
resp.Header.Add(fakeHeader, v)
}
}
switch req.Method {
Expand Down

0 comments on commit 70d975e

Please sign in to comment.