Benedicht / BestHTTP-Issues

Issue tracking repo for the Best HTTP and all related Unity plugins.
https://assetstore.unity.com/publishers/4137
12 stars 1 forks source link

Local cache doesn't calculate expiration properly #209

Open Benzeliden opened 1 week ago

Benzeliden commented 1 week ago

Plugin version 3.0.11 Unity version 2021.3.37f

Hello,

I'm experimenting with caching using my dev server and apparently it looks like there is an issue with age of cache. At lease this is what I'm observing in UnityEditor:

My game does requests to my-game-server/news endpoint

Example headers received from server (that are stored in headers.cache file)

server:nginx
date:Thu, 17 Oct 2024 13:01:36 GMT
content-type:application/json; charset=utf-8
vary:Accept-Encoding
cache-control:public,max-age=120

Then I stop the game and restart it 5 minutes later - and I still see old content returned by response.

If I use postman to check the same endoint - I can clearly see content changed.

==============================================

After looking into source code I come into CanServeWithoutValidation method (Hope it's okay if I share some fragments of it)

// Calculate the current age of the cached content, described here:
// 1.) https://www.rfc-editor.org/rfc/rfc9111.html#name-freshness
// 2.) https://www.rfc-editor.org/rfc/rfc9111.html#name-calculating-age
if (content.MaxAge > 0)
{
               long current_age = content.Age;

                // If there are more than one requests accessing the same resource it's possible that the first one sets the RequestTime
                //  but ResponseTime is the same old value while the second request tries to calculate the resrouce's Age. In this case,
                // we will just use the received Age.
                if (content.ResponseTime > content.RequestTime) 
                {
// !!! this condition was false for me, always content.ResponseTime == content.RequestTime
                }
// !!! there is no else condition. So current_age is always 0. I can see it if I put Debug.Log

So as I undestand my issue is that content.Age = 0 and there is no code that will recalculate current_age

I put this else block as a quick fix:


                else
                {
// for some reason content.Date is in my timezone (UTC+2), so using DateTime.Now, not UtcNow
                    current_age = Max(0, (int)(DateTime.Now - content.Date).TotalSeconds);
                }

with this it looks fine

but I'm hoping for a more proper solution to this issue

Benedicht commented 1 week ago

Thanks for the report, i'm going to investiage it. content.Age should be a problem, it only contains the value sent from an intermediary (the content might sent by a proxy, where it's already aged). So it's part of the calculation, but the client doesn't update it, it uses the time difference between the current time and when the response (content) received.

Benedicht commented 1 week ago

I think if (content.ResponseTime > content.RequestTime) should be if (content.ResponseTime <= content.RequestTime).