mirror of
https://codeberg.org/VnPower/PixivFE
synced 2024-12-06 19:16:23 +01:00
rework caching functions
This commit is contained in:
+59
-34
@@ -42,6 +42,19 @@ type CachedItem struct {
|
||||
ExpiresAt time.Time
|
||||
}
|
||||
|
||||
// CachePolicy defines the caching behavior for a request.
|
||||
type CachePolicy struct {
|
||||
ShouldUseCached bool // whether to attempt fetching from the cache
|
||||
ShouldStore bool // whether to store the API response in the cache after retrieval
|
||||
CachedResponse *SimpleHTTPResponse // the cached response if available and valid
|
||||
}
|
||||
|
||||
// CachingResult encapsulates the response and whether it was retrieved from the cache.
|
||||
type CachingResult struct {
|
||||
Response *SimpleHTTPResponse
|
||||
FromCache bool
|
||||
}
|
||||
|
||||
var (
|
||||
retryClient *retryablehttp.Client
|
||||
cacheSeed uint64
|
||||
@@ -116,20 +129,17 @@ func generateCacheKey(url, userToken string) string {
|
||||
return fmt.Sprintf("%x", hash)
|
||||
}
|
||||
|
||||
// shouldUseCache determines the caching policy for a given request.
|
||||
//
|
||||
// It returns three values:
|
||||
// - shouldFetch: whether to attempt fetching from the cache.
|
||||
// - shouldStore: whether to store the response in the cache after retrieval.
|
||||
// - cachedResponse: the cached response if available and valid.
|
||||
func shouldUseCache(rawURL, userToken string, incomingHeaders http.Header) (shouldFetch bool, shouldStore bool, cachedResponse *SimpleHTTPResponse) {
|
||||
// determineCachePolicy determines the caching policy for a given request.
|
||||
// It returns a CachePolicy struct indicating whether to fetch from cache,
|
||||
// whether to store the response in cache, and the cached response if available.
|
||||
func determineCachePolicy(rawURL, userToken string, headers http.Header) CachePolicy {
|
||||
if !config.GlobalConfig.CacheEnabled {
|
||||
return false, false, nil
|
||||
return CachePolicy{}
|
||||
}
|
||||
|
||||
parsedURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return false, false, nil
|
||||
return CachePolicy{}
|
||||
}
|
||||
|
||||
urlPath := path.Clean(parsedURL.Path)
|
||||
@@ -137,49 +147,61 @@ func shouldUseCache(rawURL, userToken string, incomingHeaders http.Header) (shou
|
||||
// Check if the path is excluded from caching
|
||||
for _, exclPath := range excludedCachePaths {
|
||||
if strings.HasPrefix(urlPath, exclPath) {
|
||||
return false, false, nil
|
||||
return CachePolicy{}
|
||||
}
|
||||
}
|
||||
|
||||
cacheKey := generateCacheKey(rawURL, userToken)
|
||||
|
||||
// Check if cache invalidation is requested
|
||||
redirectedHeader := incomingHeaders.Get("X-Handled-Redirected")
|
||||
redirectedHeader := headers.Get("X-Handled-Redirected")
|
||||
if strings.Contains(strings.ToLower(redirectedHeader), "true") {
|
||||
cache.Remove(cacheKey)
|
||||
return false, false, nil
|
||||
return CachePolicy{}
|
||||
}
|
||||
|
||||
// Attempt to fetch from cache
|
||||
if cachedItem, found := cache.Get(cacheKey); found {
|
||||
item := cachedItem.(CachedItem)
|
||||
if time.Now().Before(item.ExpiresAt) {
|
||||
return false, false, item.Response
|
||||
return CachePolicy{
|
||||
ShouldUseCached: false,
|
||||
CachedResponse: item.Response,
|
||||
}
|
||||
}
|
||||
// Cache expired
|
||||
cache.Remove(cacheKey)
|
||||
}
|
||||
|
||||
// Determine if response should be cached based on headers
|
||||
cacheControl := incomingHeaders.Get("Cache-Control")
|
||||
shouldStore = cacheControl == "" || !strings.Contains(strings.ToLower(cacheControl), "no-cache")
|
||||
cacheControl := headers.Get("Cache-Control")
|
||||
shouldStore := cacheControl == "" || !strings.Contains(strings.ToLower(cacheControl), "no-store")
|
||||
|
||||
return true, shouldStore, nil
|
||||
return CachePolicy{
|
||||
ShouldUseCached: shouldStore, // Use cached version if storage is allowed
|
||||
ShouldStore: shouldStore,
|
||||
}
|
||||
}
|
||||
|
||||
// handleCaching manages the caching logic during and after a request.
|
||||
// manageCaching manages the caching logic during and after a request.
|
||||
// It either returns a cached response or allows the request to proceed and optionally caches the new response.
|
||||
func handleCaching(rawURL, userToken string, incomingHeaders http.Header, resp *SimpleHTTPResponse) (*SimpleHTTPResponse, bool) {
|
||||
shouldFetch, shouldStore, cachedResponse := shouldUseCache(rawURL, userToken, incomingHeaders)
|
||||
if !shouldFetch && cachedResponse != nil {
|
||||
return cachedResponse, true
|
||||
func manageCaching(rawURL, userToken string, headers http.Header, response *SimpleHTTPResponse) CachingResult {
|
||||
policy := determineCachePolicy(rawURL, userToken, headers)
|
||||
if policy.ShouldUseCached && policy.CachedResponse != nil {
|
||||
return CachingResult{
|
||||
Response: policy.CachedResponse,
|
||||
FromCache: true,
|
||||
}
|
||||
}
|
||||
|
||||
if shouldStore && resp != nil {
|
||||
if policy.ShouldStore && response != nil {
|
||||
ttl := config.GlobalConfig.CacheTTL
|
||||
parsedURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return resp, false
|
||||
return CachingResult{
|
||||
Response: response,
|
||||
FromCache: false,
|
||||
}
|
||||
}
|
||||
urlPath := path.Clean(parsedURL.Path)
|
||||
for _, shortPath := range shortTTLPaths {
|
||||
@@ -190,12 +212,15 @@ func handleCaching(rawURL, userToken string, incomingHeaders http.Header, resp *
|
||||
}
|
||||
|
||||
cache.Add(generateCacheKey(rawURL, userToken), CachedItem{
|
||||
Response: resp,
|
||||
Response: response,
|
||||
ExpiresAt: time.Now().Add(ttl),
|
||||
})
|
||||
}
|
||||
|
||||
return resp, false
|
||||
return CachingResult{
|
||||
Response: response,
|
||||
FromCache: false,
|
||||
}
|
||||
}
|
||||
|
||||
// makeRequest is a helper function that encapsulates the common logic for making HTTP requests.
|
||||
@@ -300,13 +325,13 @@ func executeGetWithRetries(
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
tokenManager.MarkTokenStatus(token, token_manager.Good)
|
||||
|
||||
// Handle caching logic after we receieve an HTTP 200 response
|
||||
cachedResp, isCached := handleCaching(url, userToken, incomingHeaders, resp)
|
||||
if isCached {
|
||||
return cachedResp, nil
|
||||
// Handle caching logic after we receive an HTTP 200 response
|
||||
cachingResult := manageCaching(url, userToken, incomingHeaders, resp)
|
||||
if cachingResult.FromCache {
|
||||
return cachingResult.Response, nil
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
return cachingResult.Response, nil
|
||||
}
|
||||
|
||||
lastErr = i18n.Errorf("HTTP status code: %d", resp.StatusCode)
|
||||
@@ -336,10 +361,10 @@ func retryRequest(
|
||||
return executeSinglePostRequest(ctx, reqFunc, userToken, url)
|
||||
}
|
||||
|
||||
// Handle caching logic before we send a request
|
||||
shouldFetch, _, cachedResponse := shouldUseCache(url, userToken, incomingHeaders)
|
||||
if !shouldFetch && cachedResponse != nil {
|
||||
return cachedResponse, nil
|
||||
// Determine caching policy before we send a request
|
||||
policy := determineCachePolicy(url, userToken, incomingHeaders)
|
||||
if !policy.ShouldUseCached && policy.CachedResponse != nil {
|
||||
return policy.CachedResponse, nil
|
||||
}
|
||||
|
||||
return executeGetWithRetries(ctx, reqFunc, userToken, url, incomingHeaders)
|
||||
|
||||
Reference in New Issue
Block a user