You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Loïc Lefèvre <ll...@fivia.com> on 2001/08/01 12:13:26 UTC
MOD_REWRITE + TOMCAT 3.2.3: MAYBE A SOLUTION
Hello everybody,
If you read all the mails, you must know all the problems
I've encouter with the mod_rewrite module.
Remember... the following rules didn't work:
------
#Don't know if it is useful ?!?
#RewriteRule ^(/.*;jsessionid=.*)$ $1 [T=jserv-servlet]
RewriteCond %{REQUEST_URI} ^/servlet* [NC]
RewriteRule ^/servlet/(.*) /lol/$1 [PT]
RewriteCond %{REQUEST_URI} !^/lol* [NC]
RewriteCond %{REQUEST_URI} !^/Image* [NC]
RewriteCond %{REQUEST_URI} !^/Elemtech* [NC]
RewriteCond %{REQUEST_URI} !^/Erreur* [NC]
RewriteCond %{REQUEST_URI} ^/.*/.*
RewriteRule ^/(.*) /lol/AdFront?access=/$1 [PT,QSA]
------
After many investigations, I decided to make my own Mapper
starting with SimpleMapper1 (look in server.xml).
So here is the code I added (line starting with a '#' are original!):
--------------------------
START --------------------------------------------------
package com.fivia.adfront;
#
#import org.apache.tomcat.core.*;
#import org.apache.tomcat.core.Constants;
#import org.apache.tomcat.util.*;
#import java.util.*;
import java.io.*;
import org.apache.oro.text.GlobCompiler;
import org.apache.oro.text.awk.AwkCompiler;
import org.apache.oro.text.awk.AwkMatcher;
import org.apache.oro.text.regex.*;
import javax.servlet.http.*;
#
#/**
# * This class will set up the data structures used by a simple patern
matching
# * alghoritm and use it to extract the path components from the request
URI.
# *
# * The interceptor will be called in standalone case, for "integrated"
mode
# * we should have all the data from the web server - that means the
# * performance of this code is not relevant for production mode if a web
# * server is used.
# *
# * This particular implementation does the following:
# * - extract the information that is relevant to matching from the Request
# * object. The current implementation deals with the Host header and the
# * request URI.
# * - Use an external mapper to find the best match.
# * - Adjust the request paths
# *
# * The execution time is proportional with the number of hosts, number of
# * context, number of mappings and with the length of the request.
# *
# * Security mappings are more complex ( method, transport are also part of
the
# * matching ). We can share the same mapping alghoritm or even the
mapper -
# * but until security code will be stable it's better to keep it
separated.
# *
# */
public class AdFrontMapper extends BaseInterceptor
#{
...
# if(debug>0)
# log( "Remove mapping " + mapping );
# }
#
#
# /* -------------------- Request mapping -------------------- */
private boolean checkConditions(String path, String[] sa, boolean
caseSensitiv )
{
org.apache.oro.text.regex.Pattern pattern;
PatternCompiler compiler = new Perl5Compiler();
PatternMatcher matcher = new Perl5Matcher();
boolean notPresent, result;
int i;
for(i=0;i<sa.length;i++)
{
log("Condition "+(i+1)+": "+sa[i]);
notPresent = (sa[i].charAt(0)=='!');
if( notPresent )
sa[i] = sa[i].substring(1);
try
{
pattern =
compiler.compile(sa[i],(caseSensitiv?Perl5Compiler.DEFAULT_MASK:Perl5Compile
r.CASE_INSENSITIVE_MASK)); // Condition
}
catch(MalformedPatternException malformedpatternexception)
{
log("\nMalformed Regular Expression:\n" +
malformedpatternexception.getMessage());
return false;
}
result = matcher.contains(new PatternMatcherInput(path), pattern);
if( notPresent )
result = !result;
if( !result )
{
log("Condition: "+(notPresent?"!":"")+sa[i]+" => not-matched");
return false;
}
else
log("Condition: "+(notPresent?"!":"")+sa[i]+" => matched");
}
return true;
}
private String applyRule(Request req, String path, String rule, String
substitution, String[] conditions, boolean conditionsCaseSensitivity )
{
String orgPath = path;
boolean matched = true;
org.apache.oro.text.regex.Pattern pattern;
PatternCompiler compiler = new Perl5Compiler();
PatternMatcher matcher = new Perl5Matcher();
log("Applying rule: "+rule+" on "+path);
try
{
pattern = compiler.compile(rule); // Rule
}
catch(MalformedPatternException malformedpatternexception)
{
log("\nMalformed Regular Expression:\n" +
malformedpatternexception.getMessage());
return null;
}
MatchResult matchresult;
int i=0, j, j1;
PatternMatcherInput patternmatcherinput;
for(patternmatcherinput = new PatternMatcherInput(path);
matcher.contains(patternmatcherinput, pattern);)
{
matchresult = matcher.getMatch();
i++;
log("Match " + i + ": " + matchresult.group(0) );
j1 = matchresult.groups();
if(j1 > 1)
{
if( checkConditions(path,conditions,
conditionsCaseSensitivity) )
{
log(" Subgroups:");
for(j = j1-1; j > 0; j--)
{
if( substitution.indexOf("$"+j) != -1 )
substitution =
replaceString(substitution,"$"+j,matchresult.group(j));
}
path = substitution;
}
else
{
matched = false;
break;
}
}
else
{
matched = false;
break;
}
}
if( i==0 )
matched = false;
if( matched )
{
int pos;
String queryParameters = null;
if( (pos = path.indexOf("?")) != -1 )
{
queryParameters = path.substring(pos+1);
path = path.substring(0,pos);
req.setQueryString(queryParameters);
}
req.setRequestURI(path);
log("rewrite "+orgPath+" -> "+(queryParameters==null?path:"split
uri="+substitution+" -> uri="+path+",
args="+queryParameters+"\nlocal path result: "+path));
}
else
log("pass through "+orgPath);
return path;
}
private String replaceString(String string, String oldString, String
newString)
{
if((string==null) || (string.length()==0) ||
(oldString==null) || (oldString.length()==0) ||
(newString==null))
return string;
StringBuffer sb = new StringBuffer(string);
int count=0;
int index=-1;
int nlen = newString.length();
int olen = oldString.length();
while(true)
{
index = string.indexOf(oldString,count);
if(index<0)
break;
sb.replace(index,index+olen,newString);
string = sb.toString();
count = index + nlen;
}
return sb.toString();
}
private void info(Request request)
{
log("##################################################################");
log("Server Name: " + request.getServerName());
log("Server Port: " + request.getServerPort());
log("Remote Addr: " + request.getRemoteAddr());
log("Remote Host: " + request.getRemoteHost());
log("Character Encoding: " + request.getCharacterEncoding());
log("Content Type: "+ request.getContentType());
log("");
log("Request Is Secure: " + request.isSecure());
log("Auth Type: " + request.getAuthType());
log("HTTP Method: " + request.getMethod());
log("Request URI: " + request.getRequestURI());
log("Servlet Path: " + request.getServletPath());
log("Path Info: " + request.getPathInfo());
log("Path Trans: " + request.getPathTranslated());
log("Query String: " + request.getQueryString());
log("");
log("Headers in this request:");
Enumeration e = request.getHeaderNames();
while (e.hasMoreElements()) {
String key = (String)e.nextElement();
String value = request.getHeader(key);
log(" " + key + ": " + value);
}
log("");
log("Parameter names in this request:");
e = request.getParameterNames();
while (e.hasMoreElements()) {
String key = (String)e.nextElement();
String[] values = request.getParameterValues(key);
String s = " " + key + " = ";
for(int i = 0; i < values.length; i++) {
s += values[i] + " ";
}
log(s+"\n");
}
}
# /** First step of request porcessing is finding the Context.
# */
# public int contextMap( Request req )
# {
//info(req);
log("contextMap( "+req.toString()+" )");
# String path = req.getRequestURI();
#
# if( path==null)
# throw new RuntimeException("ASSERT: null path in request URI");
path = applyRule(req, path,"^/servlet/(.*)","/lol/$1",new
tring[]{ "^/servlet*" },false);
path = applyRule(req, path,"^/(.*)","/lol/AdFront?access=/$1",new
String[]{ "!^/lol*", "!^/Image*", "!^/Elemtech*", "!^/Erreur*",
"^/.*/.*" },false);
if( path == null )
return 404;
# if( path.indexOf("?") >=0 )
# throw new RuntimeException("ASSERT: ? in requestURI");
#
# try
# {
# String host=req.getServerName();
# if(debug>0)
# cm.log("Host = " + host);
#
# Container container =(Container)map.getLongestPrefixMatch( host,
path );
#
# if( container == null )
# return 404;
#
# if(debug>0)
# cm.log("SM: Prefix match " + path + " -> " + container.getPath() + " "
+ container.getHandler() + " " + container.getRoles());
...
----------------------------------------------------------------------------
---------------
-----------------------------------
END ---------------------------------------------------
----------------------------------------------------------------------------
---------------
I use the jakarta package ORO 2.0.4:
http://jakarta.apache.org/builds/jakarta-oro/release/v2.0.4/jakarta-oro-2.0.
4.tar.gz
I then compile to create the mapper.jar package, put it in %TOMCAT_HOME%/lib
and replace in server.xml:
<RequestInterceptor
className="org.apache.tomcat.request.SimpleMapper1"
debug="1" />
BY
<RequestInterceptor
className="com.fivia.adfront.AdFrontMapper"
debug="1" />
Please send me any comment.
Loïc Lefèvre