Finally, a colleague helped me to get this done.
The urlrewrite.xml looks like above:
<?xml version="1.0" encoding="UTF-8"?>
<urlrewrite>
<rule match-type="regex">
<note>Allow all these requests</note>
<from>^/v1/api/(one|two|three)/(.*)$</from>
<to type="proxy" encode="false">http://admin-user:admin-password@localhost:8091/myapp/v1/api/$1/${escapePath:UTF-8:$2}</to>
</rule>
<rule match-type="regex">
<note>These requests must be authorised</note>
<from>^/v1/api/(four|five|six)(.*)$</from>
<to type="proxy" encode="false">http://localhost:8091/myapp/v1/api/$1${escapePath:UTF-8:$2}</to>
</rule>
</urlrewrite>
As you can see there are two different types of URLs for the "public" and for the "private" REST URLs. For the private URL everything works fine, it's just forwarded to my local Jetty server running at 8091. For the public URL username & password are injected into the URL. This works fine if someone does not provide username & password. Yet, what happens in case someone actually does provide them? Unfortunately, in this case still authorization is triggered in Jetty which fails in consequence (unless username & password are admins). This is not (yet) what we want.
The solution is to remove the authorization header from the original request. Inside class org.tuckey.web.filters.urlrewrite.RequestProxy there is the method setupProxyRequest(HttpServletRequest, URL). Note the added else if block inside the while loop that drops the authorization header in certain cases.
private static HttpMethod setupProxyRequest(final HttpServletRequest hsRequest, final URL targetUrl) throws IOException {
final String methodName = hsRequest.getMethod();
final HttpMethod method;
if ("POST".equalsIgnoreCase(methodName)) {
PostMethod postMethod = new PostMethod();
InputStreamRequestEntity inputStreamRequestEntity = new InputStreamRequestEntity(hsRequest.getInputStream());
postMethod.setRequestEntity(inputStreamRequestEntity);
method = postMethod;
} else if ("GET".equalsIgnoreCase(methodName)) {
method = new GetMethod();
} else {
log.warn("Unsupported HTTP method requested: " + hsRequest.getMethod());
return null;
}
method.setFollowRedirects(false);
method.setPath(targetUrl.getPath());
method.setQueryString(targetUrl.getQuery());
String userInfo = targetUrl.getUserInfo();
Enumeration e = hsRequest.getHeaderNames();
if (e != null) {
while (e.hasMoreElements()) {
String headerName = (String) e.nextElement();
if(headerName != null) headerName = headerName.trim();
if ("host".equalsIgnoreCase(headerName)) {
//the host value is set by the http client
continue;
} else if ("content-length".equalsIgnoreCase(headerName)) {
//the content-length is managed by the http client
continue;
} else if ("accept-encoding".equalsIgnoreCase(headerName)) {
//the accepted encoding should only be those accepted by the http client.
//The response stream should (afaik) be deflated. If our http client does not support
//gzip then the response can not be unzipped and is delivered wrong.
continue;
} else if (headerName.toLowerCase().startsWith("cookie")) {
//fixme : don't set any cookies in the proxied request, this needs a cleaner solution
continue;
}
else if (headerName.toLowerCase().contains("authorization") && userInfo != null) {
// Removed authorization header when userInfo is present
continue;
}
Enumeration values = hsRequest.getHeaders(headerName);
while (values.hasMoreElements()) {
String headerValue = (String) values.nextElement();
log.info("setting proxy request parameter:" + headerName + ", value: " + headerValue);
method.addRequestHeader(headerName, headerValue);
}
}
}
if (userInfo != null) {
String headerValue = "Basic " + new String(Base64.encodeBase64(userInfo.getBytes()));
if ( log.isInfoEnabled()) log.info("setting proxy request parameter: Authorization, value: " + headerValue);
method.addRequestHeader("Authorization", headerValue);
}
if ( log.isInfoEnabled() ) log.info("proxy query string " + method.getQueryString());
return method;
}
The web.xml looks like this:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>URL Rewriting proxy</display-name>
<servlet>
<servlet-name>default</servlet-name>
<!-- Standard Tomcat default servlet -->
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<!-- Standard Tuckey default UrlRewriteFilter class -->
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
</web-app>
<set type="header" name="WWW-Authenticate"></set>? Or maybe an unpaired tag with no (empty) text child? - Christopher Schultz