You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wookie.apache.org by ps...@apache.org on 2011/10/31 15:12:58 UTC
svn commit: r1195465 - in /incubator/wookie/branches/0.9.1: RELEASE_NOTES
src/org/apache/wookie/proxy/ProxyClient.java
src/org/apache/wookie/proxy/ProxyServlet.java
Author: psharples
Date: Mon Oct 31 14:12:57 2011
New Revision: 1195465
URL: http://svn.apache.org/viewvc?rev=1195465&view=rev
Log:
Updates for WOOKIE-283 - Proxy classes ported from trunk
Modified:
incubator/wookie/branches/0.9.1/RELEASE_NOTES
incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyClient.java
incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyServlet.java
Modified: incubator/wookie/branches/0.9.1/RELEASE_NOTES
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/0.9.1/RELEASE_NOTES?rev=1195465&r1=1195464&r2=1195465&view=diff
==============================================================================
--- incubator/wookie/branches/0.9.1/RELEASE_NOTES (original)
+++ incubator/wookie/branches/0.9.1/RELEASE_NOTES Mon Oct 31 14:12:57 2011
@@ -71,6 +71,7 @@ Improvements
* WOOKIE-250 - Improve license files
* WOOKIE-255 - Change file names to not include version numbers in features
* WOOKIE-257 - Remove JUnit dependency for binary releases
+ * WOOKIE-283 - Logging into admin interface inteferes with API calls
New Features
============
Modified: incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyClient.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyClient.java?rev=1195465&r1=1195464&r2=1195465&view=diff
==============================================================================
--- incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyClient.java (original)
+++ incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyClient.java Mon Oct 31 14:12:57 2011
@@ -14,14 +14,11 @@
package org.apache.wookie.proxy;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
import java.util.ArrayList;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
@@ -30,15 +27,14 @@ import org.apache.commons.configuration.
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
-import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScope;
-import org.apache.commons.httpclient.auth.AuthenticationException;
import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
-import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
/**
@@ -48,24 +44,29 @@ public class ProxyClient {
static Logger fLogger = Logger.getLogger(ProxyClient.class.getName());
- private String fContentType = "text/plain";
private String fProxyUsername = null;
private String fProxyPassword = null;
- private String fBase64Auth = null;
+ //private String fBase64Auth = null;
private NameValuePair[] parameters = null;
private boolean fUseProxyAuthentication = false;
@SuppressWarnings("unchecked")
public ProxyClient(HttpServletRequest request){
+ //
+ // If the request includes authn parameters, create proxy auth headers
+ //
String proxyUserName = request.getParameter("username");
String proxyPassword = request.getParameter("password");
- String base64Auth = request.getHeader("Authorization");
+ //String base64Auth = request.getHeader("Authorization");
if(proxyUserName != null && proxyPassword != null )
this.setProxyAuthConfig(proxyUserName, proxyPassword);
- if(base64Auth != null)
- this.setBase64AuthConfig(base64Auth);
+ //if(base64Auth != null)
+ // this.setBase64AuthConfig(base64Auth);
+
+ //
+ // Filter out instructions to the proxy server from the original request parameters
+ //
filterParameters(request.getParameterMap());
- fContentType = request.getContentType();
}
private void setProxyAuthConfig(String username, String password){
@@ -74,40 +75,52 @@ public class ProxyClient {
fProxyPassword = password;
}
- private void setBase64AuthConfig(String base64Auth){
- fUseProxyAuthentication = true;
- fBase64Auth = base64Auth;
- }
-
- public String getCType(){
- return fContentType;
- }
-
- public String get(String url, Configuration properties) throws Exception {
- fLogger.debug("GET from " + url); //$NON-NLS-1$
- GetMethod method = new GetMethod(url);
- method.setDoAuthentication(true);
- return executeMethod(method, properties);
- }
-
- public String post(String uri, String xmlData, Configuration properties) throws Exception {
- fLogger.debug("POST to " + uri); //$NON-NLS-1$
- PostMethod method = new PostMethod(uri);
- method.setDoAuthentication(true);
-
- if(this.parameters.length > 0) {
- method.addParameters(this.parameters);
- } else {
- method.setRequestEntity(new StringRequestEntity(xmlData, "text/xml", "UTF8"));//$NON-NLS-1$ //$NON-NLS-2$
- }
-
- return executeMethod(method, properties);
+ //private void setBase64AuthConfig(String base64Auth){
+ // fUseProxyAuthentication = true;
+ // fBase64Auth = base64Auth;
+ //}
+
+ /**
+ * Process a proxied GET request
+ * @param url the URL to GET
+ * @param request the original request object
+ * @param properties the servlet configuration
+ * @return a ResponseObject from the remote site
+ * @throws Exception
+ */
+ public ResponseObject get(String url, HttpServletRequest request, Configuration properties) throws Exception {
+ fLogger.debug("GET from " + url); //$NON-NLS-1$
+ GetMethod method = new GetMethod(url);
+ method.setDoAuthentication(true);
+ return executeMethod(method, request, properties);
}
+
+ /**
+ * Process a proxied POST request
+ * @param url the URL to POST
+ * @param xmlData the body of the request
+ * @param request the original request object
+ * @param properties the servlet configuration
+ * @return a ResponseObject from the remote site
+ * @throws Exception
+ */
+ public ResponseObject post(String url , HttpServletRequest request, Configuration properties) throws Exception {
+ fLogger.debug("POST to " + url); //$NON-NLS-1$
+ PostMethod method = new PostMethod(url);
+ method.setDoAuthentication(true);
+
+ if(this.parameters.length > 0) {
+ method.addParameters(this.parameters);
+ } else {
+ method.setRequestEntity(new InputStreamRequestEntity(request.getInputStream()));
+ }
+
+ return executeMethod(method, request, properties);
+ }
/**
* Processes the parameters passed through to the request,
* removing the parameters used by the proxy itself
- * @return
*/
private void filterParameters(Map<Object,Object> umap){
Map<Object, Object> map = new HashMap<Object, Object>(umap);
@@ -124,78 +137,102 @@ public class ProxyClient {
}
parameters = params.toArray(new NameValuePair[params.size()]);
}
+
+ /**
+ * Execute the request and return the components of the response
+ * @param method the method to use, e.g. POST or GET
+ * @param request the original request
+ * @param properties the configuration of the servlet
+ * @return a ResponseObject containing both the response body and all headers returned
+ * @throws Exception
+ */
+ private ResponseObject executeMethod(HttpMethod method, HttpServletRequest request, Configuration properties) throws Exception{
+ ResponseObject responseObject = new ResponseObject();
- private String executeMethod(HttpMethod method, Configuration properties) throws Exception, AuthenticationException {
- // Execute the method.
- try {
- HttpClient client = new HttpClient();
- // set the clients proxy values if needed
- ConnectionsPrefsManager.setProxySettings(client, properties);
-
- if(fUseProxyAuthentication){
- if (fBase64Auth != null) {
- method.setRequestHeader("Authorization", fBase64Auth);
- }
- else {
- List<String> authPrefs = new ArrayList<String>(2);
- authPrefs.add(AuthPolicy.DIGEST );
- authPrefs.add(AuthPolicy.BASIC);
- client.getParams().setParameter (AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
- // send the basic authentication response even before the server gives an unauthorized response
- client.getParams().setAuthenticationPreemptive(true);
- // Pass our credentials to HttpClient
- client.getState().setCredentials(
- new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM),
- new UsernamePasswordCredentials(fProxyUsername, fProxyPassword));
- }
- }
-
- // Add user language to http request in order to notify server of user's language
- Locale locale = Locale.getDefault();
-
- method.setRequestHeader("Accept-Language", locale.getLanguage()); //$NON-NLS-1$
- method.setRequestHeader("Content-Type", fContentType);
- int statusCode = client.executeMethod(method);
-
- if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED) {
- Header hType = method.getResponseHeader("Content-Type");
- if (hType != null) fContentType = hType.getValue();
- // for now we are only expecting Strings
- //return method.getResponseBodyAsString();
- return readFully(new InputStreamReader(method.getResponseBodyAsStream(), "UTF-8"));
- }
- else if (statusCode == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED || statusCode == HttpStatus.SC_UNAUTHORIZED)
- throw new AuthenticationException("Authentication failed:"+ method.getStatusLine() + ' ' + method.getURI() + ' ' + method.getStatusText());
- else {
- throw new Exception("Method failed: " + method.getStatusLine() + ' ' + method.getURI() + ' ' + method.getStatusText()); //$NON-NLS-1$
- }
- }
- catch (IOException e) {
- throw e;
- }
- finally {
- // Release the connection.
- method.releaseConnection();
- }
+ try {
+ HttpClient client = new HttpClient();
+
+ //
+ // set the clients proxy values if needed
+ //
+ ConnectionsPrefsManager.setProxySettings(client, properties);
+
+ //
+ // Add in original request headers
+ //
+ @SuppressWarnings("unchecked")
+ Enumeration<String> headers = request.getHeaderNames();
+ while(headers.hasMoreElements()){
+ String header = (String) headers.nextElement();
+
+ //
+ // We can't use content-length headers in case we altered the original body when filtering out
+ // the proxy parameters, so exclude them when adding the headers to the request
+ //
+ //
+ // We don't want to pass any authz headers along either (see WOOKIE-283)
+ //
+ if(!(header.equalsIgnoreCase("Content-Length") || header.equalsIgnoreCase("authorization"))){
+ method.addRequestHeader(header, request.getHeader(header));
+ }
+
+ }
+
+ //
+ // Include authentication if required
+ //
+ if(fUseProxyAuthentication){
+ //if (fBase64Auth != null) {
+ // method.setRequestHeader("Authorization", fBase64Auth);
+ //}
+ //else {
+ List<String> authPrefs = new ArrayList<String>(2);
+ authPrefs.add(AuthPolicy.DIGEST );
+ authPrefs.add(AuthPolicy.BASIC);
+ client.getParams().setParameter (AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
+
+ //
+ // send the basic authentication response even before the server gives an unauthorized response
+ //
+ client.getParams().setAuthenticationPreemptive(true);
+
+ //
+ // Pass our credentials to HttpClient
+ //
+ client.getState().setCredentials(
+ new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM),
+ new UsernamePasswordCredentials(fProxyUsername, fProxyPassword));
+ //}
+ }
+
+ //
+ // Excecute request and return response
+ //
+ int statusCode = client.executeMethod(method);
+ responseObject.status = statusCode;
+ responseObject.body = IOUtils.toByteArray(method.getResponseBodyAsStream());
+ responseObject.headers = method.getResponseHeaders();
+ return responseObject;
+ }
+ catch (IOException e) {
+ throw e;
+ }
+ finally {
+
+ //
+ // Release the connection.
+ //
+ method.releaseConnection();
+ }
}
-
+
/**
- * This is supposed to be the correct way to read the response instead of using getResponseBody() - which gives a runtime warning;
- *
- * See - http://mail-archives.apache.org/mod_mbox/jakarta-httpclient-user/200411.mbox/%3c1101558111.4070.22.camel@localhost.localdomain%3e
- * @param input
- * @return
- * @throws IOException
+ * Inner class used to pass response parts back to the servlet
*/
- private String readFully(Reader input) throws IOException {
- BufferedReader bufferedReader = input instanceof BufferedReader ? (BufferedReader) input
- : new BufferedReader(input);
- StringBuffer result = new StringBuffer();
- char[] buffer = new char[4 * 1024];
- int charsRead;
- while ((charsRead = bufferedReader.read(buffer)) != -1) {
- result.append(buffer, 0, charsRead);
- }
- return result.toString();
+ class ResponseObject{
+ public int status;
+ public byte[] body;
+ public Header[] headers;
+
}
}
Modified: incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyServlet.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyServlet.java?rev=1195465&r1=1195464&r2=1195465&view=diff
==============================================================================
--- incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyServlet.java (original)
+++ incubator/wookie/branches/0.9.1/src/org/apache/wookie/proxy/ProxyServlet.java Mon Oct 31 14:12:57 2011
@@ -15,7 +15,6 @@
package org.apache.wookie.proxy;
import java.io.IOException;
-import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
@@ -29,6 +28,7 @@ import javax.servlet.http.HttpServletReq
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.configuration.Configuration;
+import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.auth.AuthenticationException;
import org.apache.log4j.Logger;
import org.apache.wookie.beans.IAccessRequest;
@@ -68,13 +68,17 @@ public class ProxyServlet extends HttpSe
try {
Configuration properties = (Configuration) request.getSession().getServletContext().getAttribute("properties");
+ //
// Check that the request is coming from the same domain (i.e. from a widget served by this server)
+ //
if (properties.getBoolean("widget.proxy.checkdomain") && !isSameDomain(request)){
response.sendError(HttpServletResponse.SC_FORBIDDEN,"<error>"+UNAUTHORISED_MESSAGE+"</error>");
return;
}
+ //
// Check that the request is coming from a valid widget
+ //
IPersistenceManager persistenceManager = PersistenceManagerFactory.getPersistenceManager();
IWidgetInstance instance = persistenceManager.findWidgetInstanceByIdKey(request.getParameter("instanceid_key"));
if(instance == null && !isDefaultGadget(request)){
@@ -82,7 +86,9 @@ public class ProxyServlet extends HttpSe
return;
}
+ //
// Create the proxy bean for the request
+ //
ProxyURLBean bean;
try {
bean = new ProxyURLBean(request);
@@ -91,24 +97,50 @@ public class ProxyServlet extends HttpSe
return;
}
+ //
// should we filter urls?
+ //
if (properties.getBoolean("widget.proxy.usewhitelist") && !isAllowed(bean.getNewUrl().toURI(), instance)){
response.sendError(HttpServletResponse.SC_FORBIDDEN,"<error>URL Blocked</error>");
fLogger.warn("URL " + bean.getNewUrl().toExternalForm() + " Blocked");
return;
}
+ //
+ // Create a ProxyClient instance for the request
+ //
ProxyClient proxyclient = new ProxyClient(request);
- PrintWriter out = response.getWriter();
+ ProxyClient.ResponseObject responseObject = null;
+
//TODO - find all the links etc & make them absolute - to make request come thru this servlet
- String output = "";
+
+ //
+ // Execute the request and populate the ResponseObject
+ //
if(httpMethod.equals("get")){
- output = proxyclient.get(bean.getNewUrl().toExternalForm(), properties);
- }else{
- output = proxyclient.post(bean.getNewUrl().toExternalForm(),getXmlData(request), properties);
+ responseObject = proxyclient.get(bean.getNewUrl().toExternalForm(), request, properties);
+ } else {
+ responseObject = proxyclient.post(bean.getNewUrl().toExternalForm(), request, properties);
+ }
+
+ //
+ // Set Status
+ //
+ response.setStatus(responseObject.status);
+
+ //
+ // Set Headers
+ //
+ for (Header header:responseObject.headers){
+ response.setHeader(header.getName(), header.getValue());
+ }
+
+ //
+ // Set Body
+ //
+ if(responseObject.body != null && responseObject.body.length > 0){
+ response.getOutputStream().write(responseObject.body);
}
- response.setContentType(proxyclient.getCType());
- out.print(output);
}
catch (Exception ex) {
try {
@@ -127,22 +159,6 @@ public class ProxyServlet extends HttpSe
}
/**
- * Gets the content of the request
- * @param request
- * @return
- * @throws IOException
- */
- private String getXmlData(HttpServletRequest request) throws IOException{
- // Note that we cannot use a Reader for this as we already
- // call getParameter() which works on an InputStream - and you
- // can only use an InputStream OR a Reader, not both.
- byte[] b = new byte[request.getContentLength()];
- request.getInputStream().read(b, 0, request.getContentLength());
- String xml = new String(b);
- return xml;
- }
-
- /**
* Checks that the request is from the same domain as this service
* @param request
* @param checkDomain