Tomcat: Custom Error Pages

This is the latest in my series of short posts related to configuring Tomcat, as I work on getting a Tomcat/ACF10 development environment stood up next to my existing Apache/JRun/ACF9 application stack. See the first post in the series for a bit of background.

There are several reasons you may want to set up custom error pages to be served by Tomcat when different kinds of errors or exceptions are encountered. These reasons might include:

  • Security: the default error pages served by Tomcat can include information about the server and its configuration that could be considered a vulnerability (e.g.., file paths, configuration or version information)
  • Application-specific error handling: you may want to provide site- or application-specific information about the error to assist the user (or the developer!)

Part of the servlet specification allows for the definition of error pages to be served up based on either an exception or an error code in the following format:

<web-app>
   ...
   <error-page>
      <exception-type>java.lang.NullPointerException</error-code>
      <location>/nullpointer.jsp</location>
   </error-page>

   <error-page>
      <error-code>404</error-code>
      <location>/404.html</location>
   </error-page>
   ...
</web-app>

The specific files served up can be static HTML or dynamic pages of any type supported by the server. The paths are relative to the root of the web application.

Because the default error pages served up by Tomcat include version information, I typically define a basic set of error pages for HTTP 403 and 404 status codes, place those pages in a ./errors/ folder off the Web root and then reference them in ./WEB-INF/web.xml for my application.

Tomcat: Default Web Document List

This is the sixth in my series of short posts covering the different aspects of setting up a development environment based on Tomcat and Adobe’s ColdFusion 10 application server stack. For background on this, see the initial post in the series.

The list of default documents the server will provide is specified in ./cfusion/runtime/conf/web.xml and then replaced (if specified) in the ./WEB-INF/web.xml file within each defined context. As all of the ColdFusion configuration is handled at the context level, it makes sense to make this particular change also at the context level. Find the welcome-file-list element toward the end of file ./cfusion/wwwroot/WEB-INF/web.xml and add the needed entries:

<welcome-file-list ...>
   <welcome-file>index.shtm</welcome-file>
   <welcome-file>index.cfm</welcome-file>
   <welcome-file>index.html</welcome-file>
   <welcome-file>index.htm</welcome-file>
   ...
</welcome-file-list>

Note that order does matter here: the first file found from the list will be served up when the request does not specify the file name. As shown above, we’ll look for index.shtm (which necessitates enabling SSI to function), then index.cfm, then static HTML pages index.html and index.htm. This sequence is specific to how our applications are configured; adjust accordingly per your own configuration needs.

Make the needed changes and restart the server.

Tomcat: Enabling SSI

This is the fifth in my series detailing my efforts to stand up a Tomcat/ACF10 development environment next to my existing Apache/JRun/ACF9 stack. For background, see the first post in the series.

Enabling Tomcat’s ability to process server-side includes (SSI) requires changes to two configuration files. File ./cfusion/runtime/conf/web.xml contains definitions for both a filter and a servlet for processing SSI’s, as well as a pair of corresponding servlet-mapping and filter-mapping definitions for filenames matching the *.shtml pattern. Uncomment either the filter or the servlet element (but not both), and the corresponding -mapping element. Modify the -mapping element based on the naming conventions you use and/or add additional -mapping elements, as needed.

If you decide to go the filter route on this, you should also note that the default web.xml file’s definition of the filter determines whether to run files through the SSI processing based on the MIME-type of the file. You will almost certainly have to also uncomment, and possibly supplement, the entry/entries in the MIME-type mappings in the same file.

The second file that requires a tweak, per the Tomcat SSI How-To, is ./cfusion/runtime/conf/server.xml. As noted in the docs, only contexts configured as “privileged” can use the SSI capabilities. Add the privileged="true" attribute to Context element for the ColdFusion context:

<Context
   path="/"
   docBase="/Applications/ColdFusion10/cfusion/wwwroot"
   ...
   privileged="true"
>
...
</Context>

Throw together a quick test SSI file, bounce your server, and verify that it works.

I clearly have some additional homework to do on this one, as I dont yet understand the benefits and drawbacks of the filter-vs-servlet choice above. More to come on that.

Tomcat: Restricting Access by IP

This is the fourth in my series detailing my efforts to stand up a Tomcat/ACF10 development environment next to my existing Apache/JRun/ACF9 stack. For background, see the first post in the series.

A couple items have struck me in wading around in the Tomcat docs and configuration files: the flexibility and power of Tomcat, along with the fact that there are often multiple ways to do quite a few things when it comes to configuring Tomcat. Restricting access to applications and content available via Tomcat is no exception: there are at least three ways to accomplish this. For now, primarily in the interest of getting our dev environment up and running as quickly as we can, we’ll take the simplest approach. As with access logging, we’ll configure a valve within ./cfusion/runtime/conf/server.xml. This valve will restrict access to only requests coming from the localhost:

<Host name="localhost" ... >
   ...
   <Valve
      className="org.apache.catalina.valves.RemoteAddrValve"
      allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1"
   />
   ...
</Host>

See the docs for details on this valve, but it is very straightforward: just a regex identifying the IP addresses to be allowed. Requests from any addresses not listed in the allow attribute will be blocked.

Clearly, you’d not place such a restriction on a production box, but in a dev environment I typically do not want to allow access to other boxes under normal circumstances. You’ll note that this is an all-or-nothing approach; in reality, it is more likely that we will want to at least open access to specific folders for specific addresses occasionally. This approach won’t provide that flexibility but we will return to this topic for another approach later in this series.

Make the change shown above, bounce your server, and verify that access from other systems on your network are no longer able to access pages/apps on your dev box.

Tomcat: Configuring Access Logging

This is third in my series of posts detailing my efforts to stand up a Tomcat/ACF10 development environment next to my existing Apache/JRun/ACF9 stack. For background, see the first post in the series.

Access logging in Tomcat is fairly straightforward to set up, and the official docs are very understandable. The default configuration installed with ACF10 includes an entry for access logging in ./cfusion/runtime/conf/server.xml. Toward the bottom of the file, find the <Host> element and its child access log <Valve> element.

<Host name="localhost" ... >
   <Valve
      className="org.apache.catalina.valves.AccessLogValve"
      directory="/tmp"
      prefix="access-"
      suffix=".log"
      pattern="common"
      rotatable="true"
      fileDateFormat="yyyy-MM-dd"
   />
   ...
</Host>

Most of what’s shown there is easy to understand. A couple of items are worth touching on:

  • the pattern attribute specifies what gets logged for each request; as noted in the docs “common” and “combined” are short-cuts for standard sequences of commonly-used field
  • the fileDatePattern attribute is used to specify the naming mask for the log file; it also specifies the frequency at which the log files are rotated if the logs are specified as being rotatable. Where this mask goes to the day level, access logs will be specified each day.
  • I’ve temporarily set up the access logs to be created in the /tmp folder just for convenience as I work through configuring; I will change this to have the logs created in a more standard (and more secure) location as I get closer to wrapping this up.

Configure your logs as needed, restart the server, bounce a couple requests off it, and verify that the access logs are present and functional.