}
public void invoke(HttpServletRequest request, HttpServletResponse response) throws HttpReverseProxyException, IOException
{
// proxyPathMapper can be injected by using request attribute.
HttpReverseProxyPathMapper proxyPathMapper = (HttpReverseProxyPathMapper) request.getAttribute(HttpReverseProxyConstants.PATH_MAPPER);
String localPathInfo = request.getPathInfo();
if (localPathInfo.indexOf('/', 1) == -1)
{
localPathInfo = localPathInfo + "/";
}
if (proxyPathMapper == null)
{
proxyPathMapper = proxyPathMapperProvider.findMapper(localPathInfo);
}
if (proxyPathMapper == null)
{
throw new HttpReverseProxyNotFoundException("Proxy configuration is not defined for " + localPathInfo);
}
if (proxyPathMapper.isSecured())
{
boolean allowed = false;
Set<String> allowedRoles = proxyPathMapper.getAllowedRoles();
if (allowedRoles != null)
{
ReverseProxyRequestContextProvider reverseProxyRequestContextProvider = findReverseProxyRequestContextProvider(request);
for (String allowedRole : allowedRoles)
{
if (reverseProxyRequestContextProvider.isUserInRole(request, allowedRole))
{
allowed = true;
break;
}
}
}
if (!allowed)
{
log.warn("The user is not in roles: " + allowedRoles);
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
}
if (hostHeaderValue == null)
{
if (request.getServerPort() == 80)
{
hostHeaderValue = request.getServerName();
}
else
{
hostHeaderValue = request.getServerName() + ":" + request.getServerPort();
}
}
String proxyTargetURL = proxyPathMapper.getRemoteURL(localPathInfo);
if (proxyTargetURL == null)
{
throw new HttpReverseProxyNotFoundException("Cannot translate the location path info into remote URL. " + localPathInfo);
}
String queryString = request.getQueryString();
if (queryString != null)
{
proxyTargetURL = new StringBuilder(proxyTargetURL.length() + 1 + queryString.length()).append(proxyTargetURL).append('?').append(queryString).toString();
}
final List<org.apache.http.cookie.Cookie> responseSetCookies = new ArrayList<org.apache.http.cookie.Cookie>();
// create http client for each request...
DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager, clientParams)
{
@Override
protected CookieStore createCookieStore()
{
return new BasicCookieStore()
{
@Override
public void addCookie(org.apache.http.cookie.Cookie cookie)
{
responseSetCookies.add(cookie);
}
};
}
};
if (httpRoutePlanner != null)
{
httpClient.setRoutePlanner(httpRoutePlanner);
}
// redirection should be adjusted with local host header...
httpClient.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);
HttpRequestBase httpRequest = null;
String method = request.getMethod();
if (HttpGet.METHOD_NAME.equals(method))
{
httpRequest = new HttpGet(proxyTargetURL);
}
else if (HttpHead.METHOD_NAME.equals(method))
{
httpRequest = new HttpHead(proxyTargetURL);
}
else if (HttpPost.METHOD_NAME.equals(method))
{
httpRequest = new HttpPost(proxyTargetURL);
long contentLength = NumberUtils.toLong(request.getHeader(HTTP.CONTENT_LEN));
if (contentLength > 0L)
{
HttpEntity entity = new InputStreamEntity(request.getInputStream(), contentLength);
((HttpPost) httpRequest).setEntity(entity);
}
}
else if (HttpPut.METHOD_NAME.equals(method))
{
httpRequest = new HttpPut(proxyTargetURL);
long contentLength = NumberUtils.toLong(request.getHeader(HTTP.CONTENT_LEN));
if (contentLength > 0L)
{
HttpEntity entity = new InputStreamEntity(request.getInputStream(), contentLength);
((HttpPost) httpRequest).setEntity(entity);
}
}
else if (HttpDelete.METHOD_NAME.equals(method))
{
httpRequest = new HttpDelete(proxyTargetURL);
}
else if (HttpOptions.METHOD_NAME.equals(method))
{
httpRequest = new HttpOptions(proxyTargetURL);
}
else if (HttpTrace.METHOD_NAME.equals(method))
{
httpRequest = new HttpHead(proxyTargetURL);
}
else
{
throw new HttpReverseProxyException("Unsupported method: " + method);
}
// set sso credentials if available
List<SSOSiteCredentials> credsList = getSSOSiteCredentials(proxyTargetURL, httpClient, request);
if (credsList != null && !credsList.isEmpty())
{
SSOSiteCredentials firstCreds = credsList.get(0);
if (firstCreds.isFormAuthentication() && StringUtils.equals(firstCreds.getBaseURL(), proxyTargetURL))
{
httpRequest = new HttpPost(proxyTargetURL);
List <NameValuePair> formParams = new ArrayList<NameValuePair>();
formParams.add(new BasicNameValuePair(firstCreds.getFormUserField(), firstCreds.getUsername()));
formParams.add(new BasicNameValuePair(firstCreds.getFormPwdField(), firstCreds.getPassword()));
((HttpPost) httpRequest).setEntity(new UrlEncodedFormEntity(formParams));
}
else
{
for (SSOSiteCredentials creds : credsList)
{
AuthScope authScope = new AuthScope(creds.getHost(), creds.getPort(), creds.getRealm(), creds.getScheme());
Credentials usernamePwdCreds = new UsernamePasswordCredentials(creds.getUsername(), creds.getPassword());
httpClient.getCredentialsProvider().setCredentials(authScope, usernamePwdCreds);
}
}
}
// pass most headers to proxy target...
for (Enumeration enumHeaderNames = request.getHeaderNames(); enumHeaderNames.hasMoreElements(); )
{
String headerName = (String) enumHeaderNames.nextElement();
if (StringUtils.equalsIgnoreCase(headerName, HTTP.CONTENT_LEN))
continue;
if (StringUtils.equalsIgnoreCase(headerName, HTTP.TARGET_HOST))
continue;
for (Enumeration enumHeaderValues = request.getHeaders(headerName); enumHeaderValues.hasMoreElements(); )
{
String headerValue = (String) enumHeaderValues.nextElement();
httpRequest.addHeader(headerName, headerValue);
}
}
Map<String, String> defaultRequestHeaders = proxyPathMapper.getDefaultRequestHeaders();
if (defaultRequestHeaders != null)
{
for (Map.Entry<String, String> entry : defaultRequestHeaders.entrySet())
{
httpRequest.setHeader(entry.getKey(), entry.getValue());
}
}
CookieStore cookieStore = httpClient.getCookieStore();
if (cookieStore != null)
{
Map<String, String> defaultRequestCookies = proxyPathMapper.getDefaultRequestCookies();
if (defaultRequestCookies != null)
{
for (Map.Entry<String, String> entry : defaultRequestCookies.entrySet())
{
cookieStore.addCookie(new BasicClientCookie(entry.getKey(), entry.getValue()));
}
}
}
HttpEntity httpEntity = null;
try
{
HttpResponse httpResponse = httpClient.execute(httpRequest);
httpEntity = httpResponse.getEntity();
String rewriterContextPath = localBaseURL;
if (rewriterContextPath == null)
{
rewriterContextPath = request.getContextPath() + request.getServletPath();
}
int statusCode = httpResponse.getStatusLine().getStatusCode();
// Check if the proxy response is a redirect
if (statusCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */
&& statusCode < HttpServletResponse.SC_NOT_MODIFIED /* 304 */)
{
String location = null;
Header locationHeader = httpResponse.getFirstHeader(HttpReverseProxyConstants.HTTP_HEADER_LOCATION);
if (locationHeader != null)
{
location = locationHeader.getValue();
}
if (location == null)
{
throw new HttpReverseProxyException("Recieved status code is " + statusCode + " but no " + HttpReverseProxyConstants.HTTP_HEADER_LOCATION + " header was found in the response");
}
// Modify the redirect to go to this proxy servlet rather that the proxied host
// FYI, according to rfc2616, "Location" header value must be an absolute URI.
String localPath = proxyPathMapper.getLocalPath(location);
// if the current proxy path mapper cannot map the remote location to local path, then
// try to find out a possible path mapper instead one more...
if (localPath == null)
{
HttpReverseProxyPathMapper proxyPathMapperByLocation = proxyPathMapperProvider.findMapperByRemoteURL(location);
if (proxyPathMapperByLocation != null)
{
localPath = proxyPathMapperByLocation.getLocalPath(location);
}
}
String redirectLocation = null;