2

I'm trying to cache a response to a webapi endpoint requests.

I've created a DelegatingHadler that short circuits the pipeline reusing a previously generated response, and it does not work.

What am I doing wrong? or how can I do it correctly?

This is my DH:

public class StuffCache : DelegatingHandler
{
    public const string URL_CACHED = @"/stuff-endpoint/items";

    ObjectCache cache = MemoryCache.Default;

    public StuffCache()
    {
        cache = MemoryCache.Default;
    }

    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {

        if (request.Method == HttpMethod.Get)
        {
            if (request.RequestUri.AbsolutePath.ToLower() == URL_CACHED)
            {
                HttpResponseMessage response = (HttpResponseMessage)cache["CachedItemName"];

                if (response == null)
                {
                    response = await base.SendAsync(request, cancellationToken);
                    cache.Add("CachedItemName", response, null);
                }

                return response;
            }
        }

        return await base.SendAsync(request, cancellationToken);
    }

}
Flavio CF Oliveira
  • 5,235
  • 13
  • 40
  • 63
  • Cache Response Headers? – Legends Jun 28 '16 at 18:10
  • The entire response, everything – Flavio CF Oliveira Jun 29 '16 at 10:17
  • Yes but you have to add the Cache Response Headers before you cache the whole ResponseMessage! – Legends Jun 29 '16 at 10:23
  • The browser can cache the request, if you set the cache headers in your response accordingly, but do you only want to cache the request processing on the server? Currently you only cache request processing, this means, you already have a build response in your cache. But nevertheless the browser will make a request, when using this approach. The questions is, what do u want to happen? – Legends Jun 29 '16 at 10:32
  • Sorry, i Want to get it cached Serverside first, the cache headers is not my primary concerning. i want to get the full power from the metal :D – Flavio CF Oliveira Jun 29 '16 at 14:33
  • Ok, but your code looks good without testing it bymyself. What is your problem? Any errors? – Legends Jun 29 '16 at 19:02
  • Yes, the HttpMessageResponse stored in cache becomes disposed after the first time that instance returned. – Flavio CF Oliveira Jun 30 '16 at 15:03
  • It is a reference type, you cache it and when you return it furhter down the pipe, I guess it gets disposed soemwhere at the end. Cache the Content and Headers, not the whole object.... – Legends Jun 30 '16 at 15:26

2 Answers2

2

Cimpress.Extensions.Http.Caching.InMemory is a NuGet package that offers various HTTP related utility methods, notably an HttpMessageHandler that caches the results of an HTTP GET request.

The code for the DelegatingHandler can be found on GitHub.

One of the points to consider is to cache the HttpResonseMessage.Content result separately since a stream, especially a network stream, is meant to be only read once.

thoean
  • 1,106
  • 8
  • 15
0

Caching the same entire response object isn't advisable as it's tied to the request lifecycle so you would be caching a lot more than you bargained for. You could cache the content and some other metadata (statuscode, headers, etc). On cache hit use request.GetResponse(...) then set content and values you need.

Off the top of my head steps

  1. Check cache
  2. If in cache create response from request
  3. If not in cache hit api, get data, cache content and metadata for subsequent calls making sure to set expiree to avoid stale data
Samir Banjanovic
  • 400
  • 1
  • 4
  • 16