Index: java/org/apache/commons/httpclient/HttpMethod.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java,v retrieving revision 1.18 diff -u -r1.18 HttpMethod.java --- java/org/apache/commons/httpclient/HttpMethod.java 5 Sep 2002 03:37:55 -0000 1.18 +++ java/org/apache/commons/httpclient/HttpMethod.java 6 Sep 2002 16:07:39 -0000 @@ -72,7 +72,10 @@ *

* @author Remy Maucherat * @author Rod Waldhoff + * @author Jeff Dever + * * @version $Revision: 1.18 $ $Date: 2002/09/05 03:37:55 $ + * @since 1.0 */ public interface HttpMethod { @@ -289,7 +292,8 @@ * * @return the integer status code if one was obtained, or -1 */ - public int execute(HttpState state, HttpConnection connection) throws HttpException, IOException; + public int execute(HttpState state, HttpConnection connection) + throws HttpException, IOException; /** * Recycle this method so that it can be used again. @@ -309,4 +313,23 @@ * @since 2.0 */ public StatusLine getStatusLine(); + + /** + * Whether or not I should automatically process responses where + * authentication is required (status code 401, etc.) + * + * @return true if authentications will be processed automatically + * @since 2.0 + */ + public boolean getDoAuthentication(); + + /** + * Set whether or not I should automatically process responses where + * authentication is required (status code 401, etc.) + * + * @param doAuthentication true to process authentications + * @since 2.0 + */ + public void setDoAuthentication(boolean doAuthentication); + } Index: java/org/apache/commons/httpclient/HttpMethodBase.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v retrieving revision 1.58 diff -u -r1.58 HttpMethodBase.java --- java/org/apache/commons/httpclient/HttpMethodBase.java 5 Sep 2002 04:07:46 -0000 1.58 +++ java/org/apache/commons/httpclient/HttpMethodBase.java 6 Sep 2002 16:07:39 -0000 @@ -216,6 +216,9 @@ /** Whether or not I should automatically follow redirects. */ private boolean followRedirects = false; + /** Whether or not I should automatically processs authentication. */ + private boolean doAuthentication = true; + /** Whether or not I should use the HTTP/1.1 protocol. */ private boolean http11 = true; @@ -292,6 +295,28 @@ this.http11 = http11; } + /** + * Whether or not I should automatically process responses where + * authentication is required (status code 401, etc.) + * + * @return true if authentications will be processed automatically + * @since 2.0 + */ + public boolean getDoAuthentication() { + return doAuthentication; + } + + /** + * Set whether or not I should automatically process responses where + * authentication is required (status code 401, etc.) + * + * @param doAuthentication true to process authentications + * @since 2.0 + */ + public void setDoAuthentication(boolean doAuthentication) { + this.doAuthentication = doAuthentication; + } + // ---------------------------------------------- Protected Utility Methods /** @@ -755,14 +780,22 @@ switch (statusCode) { case HttpStatus.SC_UNAUTHORIZED: case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED: - // process authentication response - if (processAuthenticationResponse(state, conn)) { + log.debug("Authorization required"); + if (doAuthentication) { //process authentication response + //if the authentication is successful, return the statusCode + //otherwise, drop through the switch and try again. + if (processAuthenticationResponse(state, conn)) { + return statusCode; + } + } else { //let the client handle the authenticaiton return statusCode; } break; case HttpStatus.SC_MOVED_TEMPORARILY: case HttpStatus.SC_MOVED_PERMANENTLY: case HttpStatus.SC_TEMPORARY_REDIRECT: + log.debug("Redirect required"); + //TODO: This block should be factored into a new //method called processRedirectResponse if (!getFollowRedirects()) { @@ -894,6 +927,7 @@ path = null; followRedirects = false; + doAuthentication = true; queryString = null; requestHeaders.clear(); responseHeaders.clear(); Index: test/org/apache/commons/httpclient/TestAuthenticator.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestAuthenticator.java,v retrieving revision 1.14 diff -u -r1.14 TestAuthenticator.java --- test/org/apache/commons/httpclient/TestAuthenticator.java 7 Aug 2002 19:24:16 -0000 1.14 +++ test/org/apache/commons/httpclient/TestAuthenticator.java 6 Sep 2002 16:07:39 -0000 @@ -89,6 +89,29 @@ junit.textui.TestRunner.main(testCaseName); } + // ------------------------------------------------------- Utility Methods + + private void checkAuthorization(UsernamePasswordCredentials cred, String methodName, String auth) throws Exception { + Hashtable table = new Hashtable(); + StringTokenizer tokenizer = new StringTokenizer(auth, ",=\""); + while(tokenizer.hasMoreTokens()){ + String key = null; + String value = null; + if(tokenizer.hasMoreTokens()) + key = tokenizer.nextToken(); + if(tokenizer.hasMoreTokens()) + value = tokenizer.nextToken(); + if(key != null && value != null){ + table.put(key.trim(),value.trim()); + } + } + String response = (String) table.get("response"); + table.put( "methodname", methodName ); + String digest = Authenticator.createDigest(cred.getUserName(),cred.getPassword(), table); + assertEquals(response, digest); + } + + // ------------------------------------------------------- TestCase Methods public static Test suite() { @@ -191,6 +214,7 @@ assertEquals(expected,method.getRequestHeader("Authorization").getValue()); } + public void testBasicAuthenticationWithMutlipleRealms() throws Exception { HttpState state = new HttpState(); state.setCredentials("realm1",new UsernamePasswordCredentials("username","password")); @@ -346,24 +370,31 @@ } } - private void checkAuthorization(UsernamePasswordCredentials cred, String methodName, String auth) throws Exception { - Hashtable table = new Hashtable(); - StringTokenizer tokenizer = new StringTokenizer(auth, ",=\""); - while(tokenizer.hasMoreTokens()){ - String key = null; - String value = null; - if(tokenizer.hasMoreTokens()) - key = tokenizer.nextToken(); - if(tokenizer.hasMoreTokens()) - value = tokenizer.nextToken(); - if(key != null && value != null){ - table.put(key.trim(),value.trim()); - } - } - String response = (String) table.get("response"); - table.put( "methodname", methodName ); - String digest = Authenticator.createDigest(cred.getUserName(),cred.getPassword(), table); - assertEquals(response, digest); + /** + * Test that the Unauthorized response is returned when doAuthentication is false. + */ + public void testDoAuthenticateFalse() throws Exception { + HttpState state = new HttpState(); + state.setCredentials("Protected", new UsernamePasswordCredentials("name", "pass")); + HttpMethod method = new SimpleHttpMethod(); + method.setDoAuthentication(false); + SimpleHttpConnection conn = new SimpleHttpConnection(); + conn.addResponse( + "HTTP/1.1 401 Unauthorized\r\n" + + "WWW-Authenticate: Basic realm=\"Protected\"\r\n" + + "Connection: close\r\n" + + "Server: HttpClient Test/2.0\r\n" + ); + conn.addResponse( + "HTTP/1.1 200 OK\r\n" + + "Connection: close\r\n" + + "Server: HttpClient Test/2.0\r\n" + ); + method.execute(state, conn); + assertNotNull(method.getResponseHeader("WWW-Authenticate")); + assertNull(method.getRequestHeader("Authorization")); + assertEquals(401, method.getStatusCode()); + }