/*
* Copyright(c) 2005 Center for E-Commerce Infrastructure Development, The
* University of Hong Kong (HKU). All Rights Reserved.
*
* This software is licensed under the GNU GENERAL PUBLIC LICENSE Version 2.0 [1]
*
* [1] http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*/
package hk.hku.cecid.piazza.corvus.core.main.listener;
import hk.hku.cecid.piazza.commons.Sys;
import hk.hku.cecid.piazza.commons.servlet.RequestListenerException;
import hk.hku.cecid.piazza.commons.servlet.http.HttpRequestAdaptor;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* HttpProxyListener is an HTTP request listener which serves as a simple
* HTTP proxy handler. It does not support HTTPS nor caching.
*
* @author Hugo Y. K. Lam
*
*/
public class HttpProxyListener extends HttpRequestAdaptor {
/**
* Perform a simple HTTP proxy operation. No caching will be provided.
*
* @see hk.hku.cecid.piazza.commons.servlet.http.HttpRequestListener#processRequest(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
public String processRequest(HttpServletRequest request,
HttpServletResponse response) throws RequestListenerException {
try {
/*
* Check whether the request server is the local server. If true, an
* error will be sent.
*/
InetAddress[] targetServerAddresses = InetAddress
.getAllByName(request.getServerName());
InetAddress localServerAddress = InetAddress.getLocalHost();
Sys.main.log.debug("Local server address: "+localServerAddress);
for (int i = 0; i < targetServerAddresses.length; i++) {
if (targetServerAddresses[i].isLoopbackAddress()
|| targetServerAddresses[i].equals(localServerAddress)) {
response.sendError(HttpURLConnection.HTTP_FORBIDDEN,
"Address not allowed");
return null;
}
}
/*
* Reconstruct the request url
*/
String requrl = request.getRequestURL().toString();
Sys.main.log.debug("REQ URL: " + requrl);
requrl = getURL(requrl);
Sys.main.log.debug("REQ URL Modified: " + requrl);
String query = request.getQueryString();
requrl = requrl + (query == null ? "" : "?" + query);
Sys.main.log.debug("REQ URL FINAL: " + requrl);
/*
* Prepare connection for the request url
*/
URL url = new URL(requrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setInstanceFollowRedirects(false);
conn.setRequestMethod(request.getMethod());
/*
* Set all the request headers
*/
Enumeration requestHeaders = request.getHeaderNames();
while (requestHeaders.hasMoreElements()) {
String requestHeaderKey = requestHeaders.nextElement()
.toString();
Enumeration enum2 = request.getHeaders(requestHeaderKey);
while (enum2.hasMoreElements()) {
String requestHeaderValue = getHeaderProperty(enum2
.nextElement().toString());
conn.addRequestProperty(requestHeaderKey,
requestHeaderValue);
Sys.main.log.debug("REQ Header: " + requestHeaderKey + "="
+ requestHeaderValue);
}
}
/*
* Set all the request parameters
*/
ServletInputStream servletInputStream = request.getInputStream();
if (request.getContentLength() > 0) {
conn.setDoOutput(true);
OutputStream targetOutputstream = conn.getOutputStream();
int b;
while ((b = servletInputStream.read()) != -1) {
targetOutputstream.write(b);
}
}
/*
* Establish the connection
*/
Sys.main.log.debug("Connecting to " + requrl);
conn.connect();
/*
* Set the response code, return if remote server error
*/
int responseCode = conn.getResponseCode();
String responseMessage = conn.getResponseMessage();
if (responseCode >= HttpURLConnection.HTTP_INTERNAL_ERROR) {
response.sendError(responseCode, responseMessage);
return null;
}
response.setStatus(responseCode);
Sys.main.log.debug("RES CODE: " + responseCode);
Sys.main.log.debug("RES Message: " + responseMessage);
/*
* Set the response headers
*/
Map reponseHeaders = conn.getHeaderFields();
Iterator reponseHeaderKeys = reponseHeaders.keySet().iterator();
while (reponseHeaderKeys.hasNext()) {
Object reponseHeaderKey = reponseHeaderKeys.next();
if (reponseHeaderKey instanceof String) {
String reponseHeaderValue = getHeaderProperty(reponseHeaders
.get(reponseHeaderKey).toString());
response.addHeader(reponseHeaderKey.toString(),
reponseHeaderValue);
Sys.main.log.debug("RES Header: " + reponseHeaderKey + "="
+ reponseHeaderValue);
}
}
/*
* Write out the response content
*/
InputStream targetInputstream = conn.getInputStream();
ServletOutputStream outs = response.getOutputStream();
int b = targetInputstream.read();
while (b != -1) {
outs.write(b);
b = targetInputstream.read();
}
outs.flush();
}
catch (Exception e) {
Sys.main.log.error("HttpProxy error: " + e);
}
return null;
}
/*
* Remove the brackets, if any, in the given header property
*/
private String getHeaderProperty(String prop) {
if (prop.startsWith("[") && prop.endsWith("]")) {
return prop.substring(1, prop.length() - 1);
}
else {
return prop;
}
}
/*
* Extract the forwarding url, if any, from the given url
*/
private String getURL(String url) {
int i = url.indexOf("/[");
if (i < 0) {
return url;
}
String host = url.substring(0, i);
url = url.substring(i + 2);
i = url.indexOf("]");
if (i < 0) {
return url;
}
url = url.substring(0, i);
if (url.indexOf("//") > -1) {
return url;
}
else {
return host + url;
}
}
}