You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wookie.apache.org by sc...@apache.org on 2010/02/16 23:27:37 UTC
svn commit: r910736 - in /incubator/wookie/trunk:
src-tests/org/apache/wookie/tests/functional/ProxyTest.java
src/org/apache/wookie/proxy/ProxyClient.java
src/org/apache/wookie/proxy/ProxyServlet.java
Author: scottbw
Date: Tue Feb 16 22:27:36 2010
New Revision: 910736
URL: http://svn.apache.org/viewvc?rev=910736&view=rev
Log:
Fixed a problem reported for WOOKIE-116 reported by Aaron Duley, whereby a formdata request results in an illegal state (STREAMED) error. This is caused by accessing parameters (which calls an InputStream) and a Reader to read content on the same request/response. I've changed the "sendXMLData" code and added more test cases to check behaviour. I've also made parts of the proxy code return more meaningful exception types to make debugging easier.
Modified:
incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ProxyTest.java
incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyClient.java
incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyServlet.java
Modified: incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ProxyTest.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ProxyTest.java?rev=910736&r1=910735&r2=910736&view=diff
==============================================================================
--- incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ProxyTest.java (original)
+++ incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/ProxyTest.java Tue Feb 16 22:27:36 2010
@@ -16,10 +16,14 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import java.util.ArrayList;
+import java.util.List;
+
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
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.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
@@ -34,7 +38,7 @@
private static final String VALID_SITE_URL = "http://incubator.apache.org/wookie/";
private static final String INVALID_SITE_URL = "DFASFAFEQ3FQ32145235123452";
private static final String BLOCKED_SITE_URL = "http://very.bad.place";
- private static final String PROTECTED_SITE_URL = "http://localhost:8080/wookie/admin";
+ private static final String PROTECTED_SITE_URL = "http://localhost:8080/wookie/admin/";
/**
* Create an instance of a widget
@@ -89,12 +93,55 @@
String url = PROXY_URL+"?instanceid_key="+instance_id_key+"&url="+BLOCKED_SITE_URL;
assertEquals(403,send(url,"GET"));
}
+
+ @Test
+ public void postWithMixedQueryAndParameters() throws Exception{
+ HttpClient client = new HttpClient();
+ 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);
+ client.getState().setCredentials(
+ new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM),
+ new UsernamePasswordCredentials("java", "java"));
+ PostMethod req;
+ req = new PostMethod(PROXY_URL+"?instanceid_key="+instance_id_key);
+ req.addParameter("url", PROTECTED_SITE_URL);
+ client.executeMethod(req);
+ int code = req.getStatusCode();
+ req.releaseConnection();
+ assertEquals(200,code);
+ }
+
+ @Test
+ public void postWithOnlyParameters() throws Exception{
+ HttpClient client = new HttpClient();
+ 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);
+ client.getState().setCredentials(
+ new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM),
+ new UsernamePasswordCredentials("java", "java"));
+ PostMethod req;
+ req = new PostMethod(PROXY_URL);
+ req.addParameter("url", PROTECTED_SITE_URL);
+ req.addParameter("instanceid_key", instance_id_key);
+ client.executeMethod(req);
+ int code = req.getStatusCode();
+ req.releaseConnection();
+ assertEquals(200,code);
+ }
@Test
public void getProtectedSiteWithoutAuth() throws Exception{
HttpClient client = new HttpClient();
HttpMethod req;
- req = new GetMethod(PROTECTED_SITE_URL);
+ req = new GetMethod(PROXY_URL+"?instanceid_key="+instance_id_key+"&url="+PROTECTED_SITE_URL);
client.executeMethod(req);
int code = req.getStatusCode();
req.releaseConnection();
@@ -104,10 +151,17 @@
@Test
public void getProtectedSiteWithBasicAuth() throws Exception{
HttpClient client = new HttpClient();
- Credentials defaultcreds = new UsernamePasswordCredentials("java", "java");
- client.getState().setCredentials(new AuthScope("localhost", 8080, AuthScope.ANY_REALM), defaultcreds);
+ 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);
+ client.getState().setCredentials(
+ new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM),
+ new UsernamePasswordCredentials("java", "java"));
HttpMethod req;
- req = new GetMethod(PROTECTED_SITE_URL);
+ req = new GetMethod(PROXY_URL+"?instanceid_key="+instance_id_key+"&url="+PROTECTED_SITE_URL);
client.executeMethod(req);
int code = req.getStatusCode();
req.releaseConnection();
Modified: incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyClient.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyClient.java?rev=910736&r1=910735&r2=910736&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyClient.java (original)
+++ incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyClient.java Tue Feb 16 22:27:36 2010
@@ -16,6 +16,7 @@
import java.io.BufferedReader;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
@@ -33,6 +34,7 @@
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.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
@@ -57,7 +59,7 @@
String proxyUserName = request.getParameter("username");
String proxyPassword = request.getParameter("password");
String base64Auth = request.getHeader("Authorization");
- if(proxyUserName != null && proxyPassword != null )
+ if(proxyUserName != null && proxyPassword != null )
this.setProxyAuthConfig(proxyUserName, proxyPassword);
if(base64Auth != null)
this.setBase64AuthConfig(base64Auth);
@@ -102,8 +104,7 @@
}
- @SuppressWarnings("unchecked")
- private String executeMethod(HttpMethod method, Configuration properties) throws Exception {
+ private String executeMethod(HttpMethod method, Configuration properties) throws Exception, AuthenticationException {
// Execute the method.
try {
HttpClient client = new HttpClient();
@@ -115,7 +116,7 @@
method.setRequestHeader("Authorization", fBase64Auth);
}
else {
- List authPrefs = new ArrayList(2);
+ List<String> authPrefs = new ArrayList<String>(2);
authPrefs.add(AuthPolicy.DIGEST );
authPrefs.add(AuthPolicy.BASIC);
client.getParams().setParameter (AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
@@ -124,12 +125,10 @@
// Pass our credentials to HttpClient
client.getState().setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM),
- // this needs to be tenc username & password!
new UsernamePasswordCredentials(fProxyUsername, fProxyPassword));
}
}
-
// Add user language to http request in order to notify server of user's language
Locale locale = Locale.getDefault();
@@ -138,23 +137,20 @@
int statusCode = client.executeMethod(method);
if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED) {
-
Header hType = method.getResponseHeader("Content-type");
fContentType = hType.getValue();
// for now we are only expecting Strings
- return method.getResponseBodyAsString();
- //return readFully(new InputStreamReader(method.getResponseBodyAsStream(), "UTF-8"));
+ //return method.getResponseBodyAsString();
+ return readFully(new InputStreamReader(method.getResponseBodyAsStream(), "UTF-8"));
}
- else if (statusCode == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED)
- throw new Exception("ERROR_PROXY");
- else if (statusCode == HttpStatus.SC_UNAUTHORIZED)
- throw new Exception("ERROR_INVALID_PASSWORD");
+ else if (statusCode == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED || statusCode == HttpStatus.SC_UNAUTHORIZED)
+ throw new AuthenticationException();
else {
throw new Exception("Method failed: " + method.getStatusLine() + ' ' + method.getURI() + ' ' + method.getStatusText() + method.getResponseBodyAsString()); //$NON-NLS-1$
}
}
catch (IOException e) {
- throw new Exception("ERROR_CONNECT", e);
+ throw e;
}
finally {
// Release the connection.
Modified: incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyServlet.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyServlet.java?rev=910736&r1=910735&r2=910736&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyServlet.java (original)
+++ incubator/wookie/trunk/src/org/apache/wookie/proxy/ProxyServlet.java Tue Feb 16 22:27:36 2010
@@ -30,14 +30,13 @@
import javax.servlet.http.HttpSession;
import org.apache.commons.configuration.Configuration;
+import org.apache.commons.httpclient.auth.AuthenticationException;
import org.apache.log4j.Logger;
import org.apache.wookie.Messages;
import org.apache.wookie.beans.Whitelist;
import org.apache.wookie.beans.WidgetInstance;
import org.apache.wookie.server.LocaleHandler;
-import java.io.BufferedReader;
-
/**
* A web proxy servlet which will translate calls for content and return them as if they came from
* this domain
@@ -105,7 +104,11 @@
}
catch (Exception ex) {
try {
- response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage());
+ if (ex instanceof AuthenticationException){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ } else {
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage());
+ }
fLogger.error(ex.getMessage());
throw new ServletException(ex);
} catch (IOException e) {
@@ -123,18 +126,15 @@
* @throws IOException
*/
private String getXmlData(HttpServletRequest request) throws IOException{
- BufferedReader br = request.getReader();
- StringBuffer sb = new StringBuffer();
- String line;
- while ((line = br.readLine()) != null) {
- sb.append(line);
- }
- br.close();
- String xml = sb.toString();
+ // 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;
}
-
private boolean isValidUser(HttpServletRequest request, boolean checkDomain){
return isSameDomain(request, checkDomain) && isValidWidgetInstance(request);
}
@@ -206,41 +206,40 @@
}
private void doParse(HttpServletRequest request) throws MalformedURLException, UnsupportedEncodingException{
-
URL proxiedEndPointURL = null;
String endPointURL = null;
+ // Try to find a "url" parameter from the QueryString of the request
String file = request.getRequestURI();
if (request.getQueryString() != null) {
file += '?' + request.getQueryString();
- }
- // the request didn't contain any params
- else{
+ // build the requested path
+ proxiedEndPointURL = new URL(request.getScheme(),request.getServerName(),request.getServerPort() , file);
+ // find where the url parameter is ..
+ int idx = proxiedEndPointURL.toString().indexOf("url=");
+ if(idx>-1){
+ // reconstruct the path to be proxied by removing the reference to this servlet
+ endPointURL=proxiedEndPointURL.toString().substring(idx+4,proxiedEndPointURL.toString().length());
+ }
+ }
+
+ // try to locate a POST form parameter instead
+ if (endPointURL == null)
+ endPointURL=request.getParameter("url");
+
+ // the request didn't contain any params, so throw an exception
+ if (endPointURL == null)
throw new MalformedURLException("Unable to obtain url from args");
- }
- // build the requested path
- proxiedEndPointURL = new URL(request.getScheme() ,
- request.getServerName() ,
- request.getServerPort() , file);
-
- // find where the url parameter is ..
- int idx = proxiedEndPointURL.toString().indexOf("url=");
- if(idx>-1){
- // reconstruct the path to be proxied by removing the reference to this servlet
- endPointURL=proxiedEndPointURL.toString().substring(idx+4,proxiedEndPointURL.toString().length());
- }
try {
fNewUrl = new URL(endPointURL);
- }
- catch (Exception ex) {
+ } catch (Exception ex) {
// try decoding the URL
fNewUrl = new URL(URLDecoder.decode(endPointURL, "UTF-8"));
}
}
public URL getNewUrl() {
-
return fNewUrl;
}