aliostad / CacheCow

An implementation of HTTP Caching in .NET Core and 4.5.2+ for both the client and the server
MIT License
847 stars 172 forks source link

Question: Assistance with `.net60` WebApi #285

Closed Mike-E-angelo closed 2 years ago

Mike-E-angelo commented 2 years ago

Pardon the mess here if this is not the best place to post this. I have been tracking down several caching issues with my application for some time now. I encountered this project and am interested in incorporating it. However, I am having some trouble doing so.

To start, my scenario is a little different. I have a "file server" that is basically a .net60 web application that has a bunch of ApiControllers. These controllers open up connections to Azure Blob storage and fetch files from there and return it to the client calling the WebApi.

Some of these files from Azure are quite large and the load time is noticeable when the cache misses. I have applied the default caching to most of these api controller methods and that seems to address some problems. However, there are a few I just cannot seem to figure out, hence my reaching out here.

The issue I am facing now is: when loading a file directly via F5 in the browser, this seems to place a cache-control: no-cache header in the request. From what I understand. that says "use cache but validate it first" with the underlying resource. Doing so calls my api controller which again fetches the file from Azure, sort of circumventing the whole point. I am primarily looking for guidance around this.

I have attempted use other sites with direct file access and they seem to return a 304 rather than the 200 that I am currently returning. So, I am thinking that the solution is returning a 304 somehow, and to start I attempted to add CacheCow (cool name btw :)) and that did not change any behavior, so the problem is a little deeper I am thinking.

The other issue is that I attempted to use the CacheCow.Servers.WebApi but that does not seem to support net6.0. I did use the Mvc Getting Started instructions and everything seems to load but as per above the caching does not work as expected (most likely due to user error).

I am hoping this is an easy fix. 🀞 Any direction you can point me in would be greatly appreciated.

aliostad commented 2 years ago

Hi Mike,

Thanks for reaching out.

First of all, you are correct. no-cache does not really do not return cache, but a server may use its cache only if it validates it first.

CacheCow essentially takes care of handling all HTTP caching semantics in the request and response. It comes in two distinct flavours of:

Your case is actually both and I think this is the source of confusion! So your scenario is not supported out of the box (and is something I might consider supporting in the future) but there is an issue with your server scenario: you are serving files and not models and CacheCow server at this point would not be suitable. In fact you have gone most of the way for implementing your own scenario but the bit which you need to add is validation. As such I think all you need is to use CacheCow.Client with in-memory storage but only if you are currently caching in memory, is that right?

Mike-E-angelo commented 2 years ago

Thank you very much for taking the time to confirm my understanding and entertain my question here @aliostad. It is appreciated. πŸ™

As such I think all you need is to use CacheCow.Client with in-memory storage but only if you are currently caching in memory, is that right?

I am currently not caching in memory and that is why I am flummoxed with my particular issue here. Ideally I'd like to pass validation and return a 304, but I am not entirely sure how to detect that the request is a validation call vs. a non-validation call.

The other issue that occurs to me is that if I use in-memory caching, then that means I am storing huge blobs of data in my server's memory, correct? I am concerned about resource/space if that is the case.

In the meantime I will see if I can get CacheCow.Client working for my scenario. πŸ‘

aliostad commented 2 years ago

If you are not caching and not intending to cache then CacheCow.Client is no good for you. All you need to do is to pass along the validation headers. It seems you are trying to rely on browser caching of your clients and want to only mediate between the browser and the end server which is Azure Blob (or AWS S3).

HTTP caching validation happens in two ways:

So since Azure does send back ETag, I suggest (and maybe you are already doing that) you return Azure's etag when you serve the file and then check for the presence of If-None-Match and if seen, copy over to your request (I assume you are using HttpClient for that) and if you get back 304, return back.

The best way to try and test it is with a CURL or Postman and use If-None-Match against Azure and play around to get a feel. I hope this makes sense and I got your issue right, if I have not please right back.

Mike-E-angelo commented 2 years ago

GOT IT... I think πŸ˜… I had no idea about Azure blob in this way. Actually, I did have a vague idea but this helps solidify it for me. Thank you for taking the time to point me in the right direction @aliostad. I believe I have enough to get out of your hair for now. Your time is appreciated!

aliostad commented 2 years ago

Pleasure. All the best πŸ‘

Mike-E-angelo commented 2 years ago

FWIW @aliostad I did end up using the MVC package as I was encountering another issue when displaying files via a viewmodel I am using. Everything works so much better now and files are loading as expected without constantly pulling from Azure.

FWIW I have you listed here (along with what feels like half of nuget πŸ˜…):

https://alpha.starbeam.one/about/acknowledgements

Thank you again for your assistance and work here with this project πŸ™