From 48d350d9e714acd4bc09ca65a747d475f07a8e8d Mon Sep 17 00:00:00 2001 From: Paulo Costa Date: Thu, 20 Apr 2023 12:07:37 -0300 Subject: [PATCH] Detach asynchronous request from current context --- httpcache.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/httpcache.go b/httpcache.go index 798a2d4..4fe5322 100644 --- a/httpcache.go +++ b/httpcache.go @@ -9,6 +9,7 @@ package httpcache import ( "bufio" "bytes" + "context" "errors" "io" "io/ioutil" @@ -108,6 +109,8 @@ type Transport struct { Cache Cache // If true, responses returned from the cache will be given an extra header, X-From-Cache MarkCachedResponses bool + // Context timeout for async requests triggered by stale-while-revalidate + AsyncRevalidateTimeout time.Duration } // NewTransport returns a new Transport with the @@ -172,11 +175,16 @@ func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error if freshness == fresh { return cachedResp, nil } else if freshness == staleWhileRevalidate { - noCacheRequest := *req - noCacheRequest.Header = noCacheRequest.Header.Clone() + bgContext := context.Background() + cancelContext := func() {} + if t.AsyncRevalidateTimeout > 0 { + bgContext, cancelContext = context.WithTimeout(bgContext, t.AsyncRevalidateTimeout) + } + noCacheRequest := req.Clone(bgContext) noCacheRequest.Header.Set("cache-control", "no-cache") go func() { - resp, err := t.RoundTrip(&noCacheRequest) + defer cancelContext() + resp, err := t.RoundTrip(noCacheRequest) if err == nil { defer resp.Body.Close() buffer := make([]byte, 4096)