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