post with authentication using inputstream

"Matthew M. Boedicker" <[email protected]> Fri, 21 Aug 2009 00:19:22 -0400
Newsgroups gmane.comp.web.httpunit.devel
Message-ID <[email protected]>
I wrote this patch to solve an issue I found with doing a POST requiring
authentication using an InputStream for the request body. On the initial
POST the InputStream is consumed and the subsequent POST with auth headers
has an empty body.

One workaround was to manually encode the auth header and set it on every
request but I could not find a way to send it on the initial request using
setAuthentication.

The only side effect this patch has is it doesn't call close() on the
InputStream after writing it. I couldn't find a good way to do this, and
maybe the InputStream should not be closed anyway since it is created
outside of httpunit?

Matthew Boedicker

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july

_______________________________________________
Httpunit-develop mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/httpunit-develop
httpunit_post_auth_inputstream.patch (text/x-patch, 3.1 KB)
### Eclipse Workspace Patch 1.0
#P httpunit
Index: httpunit/test/com/meterware/httpunit/WebClientTest.java
===================================================================
--- httpunit/test/com/meterware/httpunit/WebClientTest.java	(revision 1048)
+++ httpunit/test/com/meterware/httpunit/WebClientTest.java	(working copy)
@@ -26,8 +26,10 @@
 
 import junit.framework.TestSuite;
 
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStreamWriter;
 import java.net.*;
 import java.util.*;
@@ -403,6 +405,38 @@
         assertEquals( "authorization", "Basic dXNlcjpwYXNzd29yZA==", wr.getText() );
     }
 
+	/**
+	 * test on demand Basic Authentication with InputStream
+	 * 
+	 * @throws Exception
+	 */
+	public void testOnDemandBasicAuthenticationInputStream() throws Exception {
+		defineResource("postRequiringAuthentication", new PseudoServlet() {
+			public WebResource getPostResponse() {
+				String header = getHeader("Authorization");
+				if (header == null) {
+					WebResource webResource = new WebResource("unauthorized");
+					webResource
+							.addHeader("WWW-Authenticate: Basic realm=\"testrealm\"");
+					return webResource;
+				} else {
+					return new WebResource(getBody(), "text/plain");
+				}
+			}
+		});
+
+		String body = "something";
+		InputStream bodyStream = new ByteArrayInputStream(body.getBytes("UTF-8"));
+		PostMethodWebRequest request = new PostMethodWebRequest(getHostPath()
+				+ "/postRequiringAuthentication", bodyStream, "text/plain");
+
+		WebConversation wc = new WebConversation();
+		wc.setAuthentication("testrealm", "user", "password");
+
+		WebResponse wr = wc.getResponse(request);
+		assertEquals(body, wr.getText());
+		bodyStream.close();
+	}
 
     /**
      * Verifies that even though we have specified username and password for a realm,
Index: httpunit/src/com/meterware/httpunit/MessageBodyWebRequest.java
===================================================================
--- httpunit/src/com/meterware/httpunit/MessageBodyWebRequest.java	(revision 1048)
+++ httpunit/src/com/meterware/httpunit/MessageBodyWebRequest.java	(working copy)
@@ -159,6 +159,9 @@
          * Transmits the body of this request as a sequence of bytes.
          **/
         public void writeTo( OutputStream outputStream, ParameterCollection parameters ) throws IOException {
+            if (_source.markSupported()) {
+                mark();
+            }
             byte[] buffer = new byte[8 * 1024];
             int count = 0;
             do {
@@ -166,10 +169,18 @@
                 count = _source.read( buffer, 0, buffer.length );
             } while (count != -1);
 
-            _source.close();
+            written = true;
         }
 
+        public void mark() throws IOException {
+            if (written) {
+                _source.reset();
+            } else {
+                _source.mark(1048576);
+            }
+        }
 
+        private boolean     written = false;
         private InputStream _source;
         private String      _contentType;
     }