2

I have the following attribute declaration over an action: [ResponseCache(Location = ResponseCacheLocation.Client, Duration = 1800)]

This works great - I can see the browser using disk cache instead of reading the information from the server again. However, it still fires off each preflight request for some reason. That's really unnecessary, and I'd like to get rid of this. How can I give the same cache treatment to the preflight request associated with this endpoint?

edit:

After seeing a suggestion below, I changed this:

    {
        builder
            .AllowCredentials()
            .SetIsOriginAllowedToAllowWildcardSubdomains()
            .WithOrigins("yadda");
    }

to this:

    {
        builder
            .AllowCredentials()
            .SetIsOriginAllowedToAllowWildcardSubdomains()
            .SetPreflightMaxAge(TimeSpan.FromHours(1))
            .WithOrigins("yadda");
    }

which resulted in this traffic in the network tab where I can see the OPTIONS request going out almost every time despite these requests all taking place within seconds of one another and the GET being retrieved from disk cache:

enter image description here

Here are the response headers which display:

enter image description here

user15716642
  • 171
  • 1
  • 12

1 Answers1

1

Preflight requests are special and their caching time is not controlled by usual means but with special Access-Control-Max-Age header. Default caching time is 5 seconds. Browsers impose limits on this value:

Firefox caps this at 24 hours (86400 seconds). Chromium (prior to v76) caps at 10 minutes (600 seconds). Chromium (starting in v76) caps at 2 hours (7200 seconds). The default value is 5 seconds.

To set this header in asp.net core while configuring CORS, use SetPreflightMaxAge.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • This seems promising, but I still see no additional header added to the OPTIONS response after making this change. I also don't see any indication that the responses it has are cached since they take 50x as long as the cached GET request. – user15716642 Oct 26 '22 at 04:39
  • If there is no `Access-Control-Max-Age` header then it will not be cached (for longer that default value of 5 seconds that is). Maybe you can provide a code example of how you use `SetPreflightMaxAge`, otherwise it's hard to suggest why it doesn't work – Evk Oct 26 '22 at 09:09
  • I updated my question with an example – user15716642 Oct 26 '22 at 17:24
  • Doesn't look like it – Evk Oct 26 '22 at 17:34
  • took me a bit longer to edit it. Sorry – user15716642 Oct 26 '22 at 17:35
  • Can you reproduce this? – user15716642 Oct 28 '22 at 19:51
  • @user15716642 nope, was not able to reproduce. I tried on a simple setup with two localhost apps one calling another, and I do see "Access-Control-Max-Age" in response to OPTIONS preflight request when I use `SetPreflightMaxAge` in CORS config (so works as expected for me). – Evk Oct 30 '22 at 10:26
  • That's fine. I'll still accept it as it seems to be the correct information. I'll just assume I have some other conflicting piece in place. – user15716642 Oct 31 '22 at 13:57
  • I looked at source code of this feature and it looks pretty straightforward: if request is preflight (which by the way means it has OPTIONS type AND has specific header), and of course if CORS check passed - just add Access-Control-Max-Age header and done. So maybe you should start with simple config and see where it goes wrong from there – Evk Oct 31 '22 at 14:07
  • Yep, I think we are using both AddCors and UseCors (.NET 6 project) and I only updated the policy builder configuration in AddCors, but UseCors apparently has the same CorsPolicyBuilder set up. I duplicated the same setup code there and will see if that works later. – user15716642 Oct 31 '22 at 14:24
  • That was it. I'm not sure why AddCors and UseCors have the same exact set up options, but I just made an extension method to wire them up identically and now it's working. Thanks! – user15716642 Oct 31 '22 at 15:04