Skip to content

Instantly share code, notes, and snippets.

@jchannon
Last active September 7, 2016 17:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jchannon/364c8b2068865e1e6fa7 to your computer and use it in GitHub Desktop.
Save jchannon/364c8b2068865e1e6fa7 to your computer and use it in GitHub Desktop.
Nancy caching using Last-Modified/If-Modified-Since header (could be replaced with ETag)
public class Cache : ICache
{
private ConcurrentDictionary<string, DateTime> cacheLookup = new ConcurrentDictionary<string,DateTime>();
public Response Get(NancyContext ctx)
{
DateTime lastmodified;
if(ctx.Request.Method == "GET") //Could be POST as well I guess
{
if (!cacheLookup.TryGetValue(ctx.Request.Method + "-" + ctx.Request.Url.ToString(), out lastmodified)
{
return null;
}
if(!ctx.Request.Headers.IfModifiedSince.HasValue)
{
return null;
}
var modifiedsince = ctx.Request.Headers.IfModifiedSince.Value;
if (modifiedsince < lastmodified)
{
return null;
}
return new Response(){ StatusCode = 304 };
}
return null;
}
public void AddOrUpdate(NancyContext ctx)
{
if(ctx.Request.Method == "GET") //Could be POST as well I guess
{
var id = ctx.Request.Method + "-" + ctx.Request.Url.ToString();//GET - http://mydomain.com/products/1?foo=bar
var date = DateTime.UtcNow;
cacheLookup.AddOrUpdate(id,date,(key,value) => date);
ctx.Response.Headers.LastModified = date;
//One thing to consider is if you indirectly update a resource by updating this resource and return a Last-Modified date
//it will potentially return a 304 even thought its been indirectly updated and a newer representation is available
}
}
}
namespace Nancy.LastModified
{
using System;
using Nancy;
public class MainModule : NancyModule
{
public MainModule(ICache cache, ISomeRepoOrServiceOrOtherLayerYouLove someRepoOrServiceOrOtherLayerYouLove)
{
Get["/{int:id}"] = x => {
return someRepoOrServiceOrOtherLayerYouLove.Get(x.id);
};
Put["/{int:id}"] = x => {
var model = this.BindAndValidate<MyModel>();
someRepoOrServiceOrOtherLayerYouLove.Update(x.id,model);
return 204;
};
Delete["/{int:id}"] = x => {
someRepoOrServiceOrOtherLayerYouLove.Delete(x.id);
return 204;
};
Before += ctx => {
return cache.Get(ctx);
};
After += ctx => {
cache.AddOrUpdate(ctx);
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment