# Using mod\_rewrite with the WAS Plug-in
## 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](#CORE2PLUGIN)
2. [Alter a request which *would* be handled by the plug-in such that
it *will not* be handled by the plug-in](#PLUGIN2CORE)
- [Practical example for providing WAR file contents from IHS
filesystem](#HTACCESS)
3. [Alter a request such that the URI passed to the plug-in is
transformed](#ALTER)
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
- To configure the WAS WebServer Plug-in to defer to Apache for
processing of the request in 8.5.5.1 and later, set the Apache
environment variable "skipwas" to any value with SetEnv or SetEnvIf.
- To configure the WAS WebServer Plug-in to defer to Apache for
processing of the request prior to 8.5.5.1, use mod\_rewrite's
\[PT\] flag to avoid context roots of enterprise applications.
## 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.
- In 8.5.5.1 and later, set the Apache environment variable "skipwas"
to any value with SetEnv or SetEnvIf
- Use the mod\_rewrite techniques below to rewrite requests out of the
context root or change the Host: header.
- Modify plugin-cfg.xml manually (difficult to maintain w/
re-generation)
## Other WebSphere Plugin / Apache interactions
- [How mod\_dir interacts with the WebSphere Plugin](#MODDIR)
- [Where should you place your rewrite rules to have them run before
the Plugin?](#CONTEXT)
-----
## 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.
/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]
```
- The *PT* flag is required, as this is what lets the WebSphere
plug-in observe the results of the mod\_rewrite processing.
- The `Alias` directive isn't effective here, because that only maps a
URI to a filename on the IHS system and doesn't change the URI in
the request. If it was used, IHS would be trying to find
/servlet/members/ProjectA/V3/SignIn.do under the Document
Root.
### 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.
/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.
- In 8.5.5.1 and later, set the Apache environment variable "skipwas"
to any value with SetEnv or SetEnvIf.
```
# Make /context-root/ work for local files
Alias /context-root/ /var/www/myapp-unpacked/
# Allow access to /var/www/myapp-unpacked/
Order deny,allow
# Tell the WAS Plugin to defer to Apache
SetEnvIf Request_URI ^/context-root/.*\.css skipwas=1
```
- In earlier levels, or when you want to change the filesystem path
that will be used:
```
# Invent a new prefix, /static/ for unpacked content
Alias /static /var/www/myapp-unpacked/
# Allo access
Alias /static /var/www/myapp-unpacked/
Order deny,allow
# remove the context root, hiding it from the WebSphere Plugin
RewriteEngine on
RewriteRule ^/context-root/(.*\.(?:css|jpg|gif|js|jpeg)$) /static/$1 [PT]
# Example to serve the source code for the example JSP, even though it matches *.jsp even with fileServingEnabled=false
RewriteRule ^/context-root/example.jsp /static/example.jsp [PT]
```
The *PT* flag is required, as this is what lets the WebSphere plug-in
observe the results of the mod\_rewrite processing.
The Alias directive is not effective here, because that only maps a URI
to a filename on the IHS system and doesn't change the URI in the
request.
During request processing, the plug-in will have no interest in the new
URI of scooby\_do.jpg.
The Redirect directive would be effective here, which is somewhat slower
but updates the users browser with the proper
UR
### 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.
/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]
```
- The *PT* flag is required, as this is what lets the WebSphere
plug-in observe the results of the mod\_rewrite processing.
- The Alias directive is not effective here, because that only maps a
URI to a filename on the IHS system and doesn't change the URI in
the request. This would cause the WebSphere plug-in to handle the
request but still operate on the original URI.
- The Redirect directive would be effective here, which is somewhat
slower but updates the users browser with the proper URI
` Redirect /servlet/allready.do /servlet/already.do`
-----
## Practical Example
### Environment
In this environment, a App1.war has been deployed to WebSphere with a
context root of /app1, but we want to offload some static files under
/app1 to IHS.
Select static content from the App1.war has been extracted to a directory
beneath the IHS DocumentRoot such as /opt/IBM/HTTPServer/htdocs/static/app1
Notes:
- A directory outside of the DocumentRoot can be used, but more configuration is required.
- Don't extract the entire WAR in the IHS filesystem. It contains JSPs,
classes, and other resources that should not be served statically by IHS
and likely contain privleged information.
The following configuration stanza should be added to the <VirtualHost> that
serves /app1, or appended to httpd.conf if virtual hosts are not used:
```
RewriteEngine ON
# If the file exists under /opt/IBM/HTTPServer/htdocs/static/, rewrite it
RewriteCond %{DOCUMENT_ROOT}/static/$1 -d [OR]
RewriteCond %{DOCUMENT_ROOT}/static/$1 -f
RewriteRule (^/app1/.*) /static/$1 [PT,E=skipwas]
# Make sure /static/ is not matched to a context root of `*` for another app
RewriteRule ^/static/ - [E=skipwas]
```
## Configuration Issues
### Module Loading/Ordering
See this document on [module ordering](enable_mod_rewrite.html) 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 \, 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 \ context. They should not be in \
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](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 "//".
-----