ContentTypeFilter java servlet filter

ContentTypeFilter (gloss.servlet.ContentTypeFilter) is a java servlet filter to control the return Content-Type HTTP response header of a java servlet based on cookies and input HTTP request headers. This is particularly useful to serve MathML-enabled webpages as these should be served as text/xml or application/xhtml+xml to MathML enabled browsers such as Firefox and IE with the MathPlayer plugin but served as text/html to other web-clients. It is not possible to set this header with apache httpd's module mod_headers, and many java servlet appications are difficult or impossible to configure in this respect. (I use this filter for blogging applications.)

Because browsers change their specs and new browsers and web agents come along frequently it is necessary for this filter to be configurable. My filter can be confugured to test the HTTP headers of the incoming request and also any cookies sent by the web agent to decide what mime type to set in the response Content-Type header.

The configuration is set in a filter parameter called "Commands". This takes the form of a sequence of tests or commands, one per line. The overall format is shown in the following

  Test1
  Test2
  Test3
  Command1
  Test4 
  Test5
  Command2
  Test6
  Command3
  Command4

which means, "if Test1 and Test2 and Test3 then Command1 else if Test4 and Test5 then Command2 else if Test6 then Command3 else Command4". Note that only one command will ever be executed. The tests are "TestHeader" (to test a HTTP header field) and "TestCookie" (to test a cookie) and the commands are "SetContentType" (to set Content-Type) and "NoFilter" (to pass the document through unchanged).

More specifically, the syntax for commands/tests is:

  SetContentType [mimettype [comments]]
  NoFilter [comments]
  TestHeader fieldname [regexpr [comments]]
  TestCookie cookiename [regexpr [comments]]

The command line is parsed into words separated by spaces. Thus no spaces are allowed in mimettype fieldname cookiename regexpr, etc.

SetContentType sets the Content-Type header to "mimetype". If a ";charset=..." section is required this MUST be given explicitly. The default when "mimetype" is absent is to use the filtered response without any charset. (This is also the default if no command in the configuration is executed at all.)

NoFilter passes the response through unfiltered.

TestHeader tests HTTP header with name "fieldname". If it is absent the test fails. If it is present (and if it matches regular expression "regexpr" if this is also present) the test succeeds.

TestCookie tests cookie with name "cookiename". If it is absent the test fails. If it is present (and if it matches regular expression "regexpr" if this is also present) the test succeeds.

All additional text on the command/test lines are ignored and can be used for comments.

Example:

    <filter>
        <filter-name>ContentTypeFilter</filter-name>
        <filter-class>gloss.servlet.ContentTypeFilter</filter-class>
        <init-param>
            <param-name>Commands</param-name>
            <param-value>
              TestHeader Accept application/xhtml\+xml   ; test if browser recognises this mimetype
              SetContentType application/xhtml+xml       ; if so set this mimetype
              TestHeader User-Agent MathPlayer           ; else test if browser has MathPlayer plugin
              SetContentType text/xml                    ; if so set this mimetype
              TestCookie useMathML ^true$                ; else test if cookie useMathML is set to true
              SetContentType text/xml                    ; if so set this mimetype
              NoFilter                                   ; else don't perform filtering
            </param-value>
        </init-param>
        <init-param>
            <param-name>EnableLogging</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

There is also a parameter "EnableLogging" which when "true" forces logging of a copious amount of detail about what the filter is doing for debugging. (The default is "false".)

The java source code of the filter is here.

A WAR of a sample application including test servlet, web.xml file, and compiled code, etc, is here.

A test page with a "hello world" type servlet is currently available at http://mat140.bham.ac.uk:8180/contenttypefilter.

Tutorials on how to set up Tomcat, write web.xml files and configure and use filters are available on the web.

This is my first programming exercise in java for servlets. If you have problems to do with this program (bugs etc in the program itself, but not installation details which should be straightforward) or you have suggestions for (mild) extensions I would be happy to hear about them. I would be grateful to hear from you in any case if you find this program useful. (My email is R dot W dot Kaye at bham dot ac dot uk.)

ContentTypeFilter is written and copyright Richard Kaye, http://web.mat.bham.ac.uk/R.W.Kaye and licensed under the GPL.