Tomcat 7 Default Servlet and History.pushState()

It is very common these days to have a website load all of its content via AJAX and use the HTML5 History.pushState() method to control the URL and the browser back button. This is done manually or through some kind of JavaScript MVC framework (AngularJS with $locationProvider.html5Mode(true), or Backbone.Router with {pushState: true}). In order for these techniques to function properly after the page is refreshed, the server must redirect requests for non-existent files to index.html silently (return the content of index.html immediately without a redirect header).

This can be achieved easily enough in Apache2 with mod_rewrite, but what about in Apache Tomcat 7? That turned out to be incredibly difficult to do without writing a special Java servlet dedicated to static files, but many StackOverflow searches later I have come up with a recipe.

In web.xml:

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
</welcome-file-list>
<error-page>
    <error-code>404</error-code>
    <location>/rewrite-404.jsp</location>
</error-page>

Then create a new file in WebContent called rewrite-404.jsp:

<% response.setStatus(HttpServletResponse.SC_OK); %>
<%@ include file="index.html" %>

This will cause existing files in WebContent to be served as usual, and all requests that would normally return a 404 error to return index.html instead with a 200 (OK) response code.