Skip to content

Instantly share code, notes, and snippets.

@elithompson
Created February 16, 2012 02:12
Show Gist options
  • Save elithompson/1840989 to your computer and use it in GitHub Desktop.
Save elithompson/1840989 to your computer and use it in GitHub Desktop.
Static resources, caching, and cache busting on AppHarbor
namespace Website
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Statics",
"s/{staticResourceVersion}/{*path}",
new { controller = "Statics", action = "Index" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
}
}
using System;
using System.Configuration;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
namespace Core.Html
{
public static class HtmlHelperExtensions
{
public static string StaticContent(this UrlHelper helper, string contentPath)
{
var staticResourceVersion = (ConfigurationManager.AppSettings.Get("appharbor.commit_id") ?? "_default").Substring(0, 8);
var staticServer = ConfigurationManager.AppSettings.Get(ConfigKeys.StaticServer);
var prefix = "";
if (!string.IsNullOrEmpty(staticServer))
prefix = "//" + staticServer;
return prefix + "/s/" + staticResourceVersion + helper.Content(contentPath);
}
}
}
@using Core.Html
<!DOCTYPE html>
<html>
<head>
<link rel="Stylesheet" href="@Url.StaticContent("~/css/style.css")" />
<script type="text/javascript" src="@Url.StaticContent("~/Scripts/script.js")"></script>
</head>
<body>
</body>
</html>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Website.Controllers
{
public class StaticsController : Controller
{
private readonly HttpResponseBase _response;
private readonly HttpRequestBase _request;
public StaticsController(HttpResponseBase response, HttpRequestBase request)
{
_response = response;
_request = request;
}
public ActionResult Index(string staticResourceVersion, string path)
{
if (!IsAllowed(path))
return new HttpStatusCodeResult(404);
if (!_request.IsLocal)
{
_response.Cache.SetCacheability(HttpCacheability.Public);
_response.Cache.SetExpires(DateTime.Now.AddYears(1));
}
return File(Server.MapPath("~/" + path), GetContentType(path));
}
private bool IsAllowed(string path)
{
if (string.IsNullOrEmpty(path))
return false;
var lowerPath = path.ToLower();
if (!lowerPath.StartsWith("img/") && !lowerPath.StartsWith("scripts/") && !lowerPath.StartsWith("css/"))
return false;
if (!lowerPath.EndsWith(".png") && !lowerPath.EndsWith(".css") && !lowerPath.EndsWith(".js"))
return false;
if (lowerPath.Contains(".."))
return false;
return true;
}
private static string GetContentType(string path)
{
var extension = Path.GetExtension(path);
switch (extension)
{
case ".js":
return "text/javascript";
case ".css":
return "text/css";
case ".png":
return "image/png";
}
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment