Forcing the WAS Plug-in to decline/handle a request

General issues

There are 3 important classes of operations one can perform with respect to changing requests and plug-in processing.
  1. Alter a request which would not be handled by the plug-in such that it will be handled by the plug-in

  2. Alter a request which would be handled by the plug-in such that it will not be handled by the plug-in

  3. Alter a request such that the URI passed to the plug-in is transformed

Generally, we discourage wholesale URI alterations that try to hide or change entire context roots as they often become unmanageable and conflict with the operation of the application. However, the general consensus is that offloading is good for performance and throughput.

Summary

Liberty issues

The Liberty web container respects the "fileServingEnabled" flag, but it is not currently a factor in the generated plugin-cfg.xml. When fileServingEnabled=false, the entire context root is forwarded to WebSphere.

There are a few ways to compensate for the generated plugin-cfg.xml, in order of preference.

Other WebSphere Plugin / Apache interactions


Examples

In the following examples, the WebSphere plug-in is configured to handle context root /app1/ and URL pattern *.do.

Note that the RewriteRule directives are kept as simple as possible, but in practice can contain regular expressions and backreferences to alter an entire class of URIs.

Alter a request which would not be handled by the plug-in such that it will be handled by the plug-in

For some unknown reason, the HTML link to a WebSphere resource doesn't include the *.jsp and is not context-root relative, so we need to alter the URI to include so the plug-in will recognize and handle the request.
WebSphere ResourceLink in HTML
/app1/SignIn.do /ProjectA/SignIn

The link as written won't be recognized by the WebSphere Plug-in, because it doesn't match any pattern in plugin-cfg.xml. When fileServingEnabled=true in the WAR (or in all cases with Liberty), only the context root is listed in plugin-cfg.xml. With fileServingEnabled=false, individual servlets and URI patterns are added, the simplest of which is *.jsp.

We can add a configuration snippet like the following to either add the extension or prefix with the context root (or both)

 
RewriteEngine on
RewriteRule /ProjectA/SignIn /app1/SignIn.jsp [PT]

Alter a request which would be handled by the plug-in such that it will not be handled by the plug-in

With "fileServingEnbabled" set to true, or in any Liberty generated plugin-cfg.xml, all requests matching an applications context root are forwarded to the application server instead of being served locally. Otherwise, individual servlet and extension patterns are forwarded.
Filesystem ResourceLink in HTMLresource requested by browser
/var/www/myapp-unpacked/.../foo.css foo.css /context-root/foo.css
/var/www/myapp-unpacked/.../example.jsp example.jsp /context-root/example.jsp

This links as written will be recognized by the WebSphere plug-in and passed to WebSphere Application Server, so we add the following directives to the IHS configuration to make sure it's served out of the filesystem.

Alter a request such that the URI passed to the plug-in is transformed

Many users are receiving 404 errors from typographical errors on the same WebSphere resource, so we provide a mapping between the erroneous name and the actual name.
WebSphere ResourceTypo
/servlet/already.do /servlet/allready.do

We change the URI that will be seen by the WebSphere plug-in as follows:

 
RewriteEngine on
RewriteRule ^/servlet/allready.do$ /servlet/already.do [PT]


Practical Example

Environment

In this environment, a WAR file has been deployed to WebSphere with a context root of SillyNew, but we require that requests for files under /SillyNew/theme/ to be served by IHS.

One motivation for this aside from freeing up WebSphere threads is that only URLs served out of the IHS filesystem can be protected with .htaccess files, WebSphere resources must be protected with <Location> containers explicitly in httpd.conf.

The WAR file has been pushed to the IHS server in the /tmp directory.

# Report the handler in Access Log LoadModule status_module modules/mod_status.so ExtendedStatus on LogFormat "%h %l %{RH}e %u %t \"%r\" %>s %b" common LoadModule rewrite_module modules/mod_rewrite.so LoadModule was_ap20_module modules/mod_was_ap20_http.so WebSpherePluginConfig /opt/.../plugin-cfg.xml # Map the WAR file into the webspace at the URL rewrite will use. Alias /SillyNewWithoutPlugin/ /tmp/SillyNew.war/ <Directory /tmp/SillyNew.war> AllowOverride AuthConfig Order Deny,Allow </Directory> # Remove the context root from requests for anything in the theme directory so it won't go through the plug-in RewriteEngine on RewriteRule ^/SillyNew/theme/(.*)$ /SillyNewWithoutPlugin/theme/$1 [PT]
The original access log entry which shows the plug-in handling the response:
    127.0.0.1 - (mod_was_ap20_http.c/-2/handler) - [01/Dec/2006:14:57:51 -0500] "GET /SillyNew/theme/blue.css HTTP/1.1" 200 9049

After enabling config change as illustrated above, IHS has attempted to serve the file from its own filesystem:
    127.0.0.1 - (mod_auth.c/401/check_user_id) - [01/Dec/2006:15:10:13 -0500] "GET /SillyNew/theme/blue.css HTTP/1.0" 401 466

After enabling above and sending the proper userid/password
    127.0.0.1 - (core.c/0/handler) user1 [01/Dec/2006:15:11:15 -0500] "GET /SillyNew/theme/blue.css HTTP/1.0" 200 9049

Configuration Issues

Module Loading/Ordering

See this document on module ordering for instructions on how to be sure that mod_rewrite (or mod_alias for Redirects) has precedence over the WebSphere Plug-in.

Using the RequestHeader directive to change the Host header

The RequestHeader can be used to influence the plug-in while it's deciding whether or not to handle the request, by specifying the "early" flag (2.2.x only). Previous versions of this FAQ incorrectly said this doesn't work. It works reliably at least on IHS 7.0 and later, with the big caveat that it cannot be tied to a subset of requests -- it affects the entire virtual host. Don't try to put it in <Location>, or combine it with mod_rewrite [E= or SetEnvIf, the timing does not work. You must use the "early" flag.

Forcing the WAS Plugin to decline a request

In 8.5.5.1 and later, you can set the "skipwas" variable with SetEnvIf to force the plugin to decline to handle a request.

Using .htaccess files to change requests that would be handled by the plugin

.htaccess files are only processed by IHS after a request has been mapped to a local file, therefore .htaccess files cannot be the mechanism used to prevent the plug-in from handling a URL.

Combining mod_rewrite flags

In some more complicated configurations, multiple mod_rewrite rules may potentially operate on the same incoming URL. In addition to the PassThrough flag (PT), the Last (L) flag is often used to end rewriting with the current rule. Flags are combined by separating them with commas as in the following:

 # Transparently rewrite anything matching *.do under /servlet/app1 and stop rewrite processing (L=Last flag)
RewriteRule /servlet/app1/(.*\.do) /servlet/$1.jsp [PT,L]
RewriteRule ... 

Hide a context root

If your app is deployed to /ourapp, and you only host 1 application, and you want to hide /ourapp from the browser completely, you can add the /ourapp prefix to each request internally.

 RewriteEngine on
RewriteRule ^(?!/ourapp)(.*) /ourapp$1 [PT]

Using mod_dir with the websphere plugin

It's not possible to use mod_dir to to map e.g. / to /index.jsp because of checking done by mod_dir when querying the DirectoryIndex filenames through an internal subrequest.

Where should you place your rewrite rules to have them run before the Plugin?

If you want your mod_rewrite directives, and they overlap with a resource the Plugin is responsible for, then these rewrite rules should be in <VirtualHost> context. They should not be in <Directory> context nor in .htaccess files. This is a requirement because the WebSphere Plugin acts in a phase of Apache Processing that maps the request outside of the filesystem, and rewrite rules in these latter contexts would simply be not applicable.

In practice, this is not a troublesome limitation, because it agrees with best practice for mod_rewrite.

General rewrite gotchas

See rewrite.html for some more esotric concerns with using mod_rewrite.

Historical Issues

2.0 Alias directive causes plug-in to decline handling request

In WebSphere Plug-in versions prior to 5.0.2.6 / 5.1.0.4, the existence of an Alias for a URI would disable plug-in processing regardless of whether or not the result of the Alias matched or did not match a pattern in plugin-cfg.xml.

There may be some configurations which exploit this behavior to serve things such as images out of the filesystem instead of from WebSphere using an Alias directive -- upgraders will find they must replace this Alias directive with an equivalent RewriteRule directive.

Incorrect: Alias /servlet/images/ /images/
Correct  : RewriteRule /servlet/images/(.*) /images/$1 [PT]

1.3 Plugin crashes if mod_alias has higher priority than plug-in

Between versions 5.1.1 and 5.1.1.6 (inclusive) of the WebSphere plug-in for IHS 1.3, a crash can be encountered if mod_alias is higher priority than the plug-in and an Alias directive operates on a URI that will be handled by the plug-in.

Apache 2.0: Leading double-slash ("//") does not match /* context root

The WAS plugin does not match /* to // which may be exploited in Apache 2.0 / IHS 6.1 and earlier to cause a request to be skipped by the WAS Plug-in.

In Apache 2.2 / IHS 7.0 and later, a leading sequence of slashes in a URL is collapsed to a single slash, so it is not possible to send a URL down to the Plugin and retain a leading "//".


Provide feedback on the IBM HTTP Server forum on IBM developerWorks.