You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by al...@apache.org on 2007/10/14 14:46:26 UTC

svn commit: r584535 - in /jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler: HTTPSampleResult.java HTTPSampler.java HTTPSampler2.java HTTPSamplerBase.java PostWriter.java

Author: alf
Date: Sun Oct 14 05:46:26 2007
New Revision: 584535

URL: http://svn.apache.org/viewvc?rev=584535&view=rev
Log:
Make the HTTP PUT behave like HTTP POST, i.e. HTTP PUT will get a request body similar to HTTP POST, but not multipart is supported for PUT.
Make the HTTP DELETE behave like HTTP GET, i.e. it supports parameters.
Some code restucturing to allow SoapSampler to soon use the code of HttpSampler2 to construct the request.

The bugs for improving better support for the various HTTP methods will not be set to fixed yet, I want to add some unit tests first. At that moment, I will also add description of these changes to the changes.xml

Modified:
    jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampleResult.java
    jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler.java
    jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler2.java
    jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
    jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/PostWriter.java

Modified: jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampleResult.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampleResult.java?rev=584535&r1=584534&r2=584535&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampleResult.java (original)
+++ jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampleResult.java Sun Oct 14 05:46:26 2007
@@ -105,9 +105,10 @@
 			sb.append(' ');
 			sb.append(u.toString());
             sb.append("\n");
-			if (HTTPSamplerBase.POST.equals(method)) {
+            // Include request body if it is a post or put
+            if (HTTPSamplerBase.POST.equals(method) || HTTPSamplerBase.PUT.equals(method)) {
                 sb.append("\nPOST data:\n");
-				sb.append(queryString);
+                sb.append(queryString);
                 sb.append("\n");
             }
             if (cookies.length()>0){

Modified: jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler.java?rev=584535&r1=584534&r2=584535&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler.java (original)
+++ jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler.java Sun Oct 14 05:46:26 2007
@@ -95,18 +95,32 @@
 	}
 
     private void setPutHeaders(URLConnection conn)
-     {
-         String filename = getFilename();
-         if ((filename != null) && (filename.trim().length() > 0))
-         {
-             conn.setRequestProperty(HEADER_CONTENT_TYPE, getMimetype());
-             conn.setDoOutput(true);
-             conn.setDoInput(true);
+    {
+        boolean hasPutBody = false;
+        // Check if any files should be uploaded
+        if (hasUploadableFiles())
+        {
+            // Set content-type if we have a value for it
+            if(getMimetype() != null && getMimetype().trim().length() > 0) {
+                conn.setRequestProperty(HEADER_CONTENT_TYPE, getMimetype());
+            }
+            hasPutBody = true;
+        }
+        // Check if any parameters should be sent as body
+        if(getSendParameterValuesAsPostBody()) {
+            hasPutBody = true;
+        }
+        // If there is any files to upload, or other body content to be sent,
+        // we set the connection to accept output
+        if(hasPutBody) {
+            conn.setDoInput(true);
+            conn.setDoOutput(true);
         }
     }
 
 	/**
 	 * Send POST data from <code>Entry</code> to the open connection.
+     * This also handles sending data for PUT requests
 	 * 
 	 * @param connection
 	 *            <code>URLConnection</code> where POST data should be sent
@@ -118,23 +132,10 @@
 		return postWriter.sendPostData(connection, this);
 	}
 
-    private void sendPutData(URLConnection conn) throws IOException {
-        String filename = getFilename();
-        if ((filename != null) && (filename.trim().length() > 0)) {
-            OutputStream out = conn.getOutputStream();
-            byte[] buf = new byte[1024];
-            int read;
-            InputStream in = new BufferedInputStream(new FileInputStream(filename));
-            while ((read = in.read(buf)) > 0) {
-                out.write(buf, 0, read);
-            }
-            in.close();
-            out.flush();
-            out.close();
-        }
+    private String sendPutData(URLConnection connection) throws IOException {
+        return postWriter.sendPostData(connection, this);
     }
 
-
 	/**
 	 * Returns an <code>HttpURLConnection</code> fully ready to attempt
 	 * connection. This means it sets the request method (GET or POST), headers,
@@ -478,8 +479,10 @@
 			if (method.equals(POST)) {
 				String postBody = sendPostData(conn);
 				res.setQueryString(postBody);
-			} else if (method.equals(PUT)) {
-                sendPutData(conn);
+            }
+            else if (method.equals(PUT)) {
+                String putBody = sendPutData(conn);
+                res.setQueryString(putBody);
             }
 			// Request sent. Now get the response:
 			byte[] responseData = readResponse(conn, res);

Modified: jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler2.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler2.java?rev=584535&r1=584534&r2=584535&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler2.java (original)
+++ jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSampler2.java Sun Oct 14 05:46:26 2007
@@ -282,9 +282,9 @@
                HTTPArgument arg = (HTTPArgument) args.next().getObjectValue();
                String parameterName = arg.getName();
                if (parameterName.length()==0){
-            	   continue; // Skip parameters with a blank name (allows use of optional variables in parameter lists)
+                   continue; // Skip parameters with a blank name (allows use of optional variables in parameter lists)
                }
-                parts[partNo++] = new StringPart(arg.getName(), arg.getValue(), contentEncoding);
+               parts[partNo++] = new StringPart(arg.getName(), arg.getValue(), contentEncoding);
             }
             
             // Add any files
@@ -341,7 +341,7 @@
             boolean hasContentTypeHeader = contentTypeHeader != null && contentTypeHeader.getValue() != null && contentTypeHeader.getValue().length() > 0; 
 
             // If there are no arguments, we can send a file as the body of the request
-            if(getArguments().getArgumentCount() == 0 && getSendFileAsPostBody()) {
+            if(!hasArguments() && getSendFileAsPostBody()) {
                 if(!hasContentTypeHeader) {
                     // Allow the mimetype of the file to control the content type
                     if(getMimetype() != null && getMimetype().length() > 0) {
@@ -358,7 +358,7 @@
                 // We just add placeholder text for file content
                 postedBody.append("<actual file content, not shown here>");
             }
-            else {            
+            else {
                 // In an application/x-www-form-urlencoded request, we only support
                 // parameters, no file upload is allowed
                 if(!hasContentTypeHeader) {
@@ -402,7 +402,7 @@
                         // it before adding it to the post request
                         String parameterName = arg.getName();
                         if (parameterName.length()==0){
-                     	   continue; // Skip parameters with a blank name (allows use of optional variables in parameter lists)
+                            continue; // Skip parameters with a blank name (allows use of optional variables in parameter lists)
                         }
                         String parameterValue = arg.getValue();
                         if(!arg.isAlwaysEncoded()) {
@@ -448,7 +448,7 @@
                     bos.close();
                 }
                 else {
-                    postedBody.append("<Multipart was not repeatable, cannot view what was sent>"); // $NON-NLS-1$
+                    postedBody.append("<RequestEntity was not repeatable, cannot view what was sent>");
                 }
             }
         }
@@ -565,6 +565,15 @@
 		return httpClient;
 	}
 
+    /**
+     * Set any default request headers to include
+     * 
+     * @param httpMethod the HttpMethod used for the request
+     */
+	protected void setDefaultRequestHeaders(HttpMethod httpMethod) {
+        // Method left empty here, but allows subclasses to override
+	}
+
 	/**
 	 * Gets the ResponseHeaders
 	 * 
@@ -750,8 +759,8 @@
 
 		String urlStr = url.toString();
 
-		log.debug("Start : sample" + urlStr);
-		log.debug("method" + method);
+		log.debug("Start : sample " + urlStr);
+		log.debug("method " + method);
 
         HttpMethodBase httpMethod = null;
 
@@ -784,13 +793,17 @@
 			    httpMethod = new GetMethod(urlStr);
 			}
 
+			// Set any default request headers
+			setDefaultRequestHeaders(httpMethod);
+            // Setup connection
 			client = setupConnection(url, httpMethod, res);
-
+			// Handle the various methods
 			if (method.equals(POST)) {
 				String postBody = sendPostData((PostMethod)httpMethod);
 				res.setQueryString(postBody);
 			} else if (method.equals(PUT)) {
-                setPutHeaders((PutMethod) httpMethod);
+                String putBody = sendPutData((PutMethod)httpMethod);
+                res.setQueryString(putBody);
             }
 
             res.setRequestHeaders(getConnectionHeaders(httpMethod));
@@ -893,17 +906,92 @@
 	}
 
     /**
-     * Set up the PUT data (if present)
+     * Set up the PUT data
      */
-	private void setPutHeaders(PutMethod put) 
-     {
-         String filename = getFilename();
-         if ((filename != null) && (filename.trim().length() > 0))
-         {
-             RequestEntity requestEntity = 
-            	 new FileRequestEntity(new File(filename),getMimetype());
-             put.setRequestEntity(requestEntity);
-         }
+    private String sendPutData(PutMethod put) throws IOException {
+        // Buffer to hold the put body, except file content
+        StringBuffer putBody = new StringBuffer(1000);
+        boolean hasPutBody = false;
+        
+        // Check if the header manager had a content type header
+        // This allows the user to specify his own content-type for a POST request
+        Header contentTypeHeader = put.getRequestHeader(HEADER_CONTENT_TYPE);
+        boolean hasContentTypeHeader = contentTypeHeader != null && contentTypeHeader.getValue() != null && contentTypeHeader.getValue().length() > 0; 
+
+        // If there are no arguments, we can send a file as the body of the request
+        if(!hasArguments() && getSendFileAsPostBody()) {
+            hasPutBody = true;
+                
+            FileRequestEntity fileRequestEntity = new FileRequestEntity(new File(getFilename()),null); 
+            put.setRequestEntity(fileRequestEntity);
+                
+            // We just add placeholder text for file content
+            putBody.append("<actual file content, not shown here>");
+        }
+        // If none of the arguments have a name specified, we
+        // just send all the values as the post body
+        else if(getSendParameterValuesAsPostBody()) {
+            hasPutBody = true;
+
+            // If a content encoding is specified, we set it as http parameter, so that
+            // the post body will be encoded in the specified content encoding
+            final String contentEncoding = getContentEncoding();
+            boolean haveContentEncoding = false;
+            if(contentEncoding != null && contentEncoding.trim().length() > 0) {
+                put.getParams().setContentCharset(contentEncoding);
+                haveContentEncoding = true;
+            }
+                
+            // Just append all the parameter values, and use that as the post body
+            StringBuffer putBodyContent = new StringBuffer();
+            PropertyIterator args = getArguments().iterator();
+            while (args.hasNext()) {
+                HTTPArgument arg = (HTTPArgument) args.next().getObjectValue();
+                String value = null;
+                if (haveContentEncoding){
+                    value = arg.getEncodedValue(contentEncoding);
+                } else {
+                    value = arg.getEncodedValue();
+                }
+                putBody.append(value);
+            }
+            String contentTypeValue = null;
+            if(hasContentTypeHeader) {
+                contentTypeValue = put.getRequestHeader(HEADER_CONTENT_TYPE).getValue();
+            }
+            StringRequestEntity requestEntity = new StringRequestEntity(putBodyContent.toString(), contentTypeValue, put.getRequestCharSet());
+            put.setRequestEntity(requestEntity);
+        }
+        // Check if we have any content to send for body
+        if(hasPutBody) {                
+            // If the request entity is repeatable, we can send it first to
+            // our own stream, so we can return it
+            if(put.getRequestEntity().isRepeatable()) {
+                ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                put.getRequestEntity().writeRequest(bos);
+                bos.flush();
+                // We get the posted bytes as UTF-8, since java is using UTF-8
+                putBody.append(new String(bos.toByteArray() , "UTF-8")); // $NON-NLS-1$
+                bos.close();
+            }
+            else {
+                putBody.append("<RequestEntity was not repeatable, cannot view what was sent>");
+            }
+            if(!hasContentTypeHeader) {
+                // Allow the mimetype of the file to control the content type
+                // This is not obvious in GUI if you are not uploading any files,
+                // but just sending the content of nameless parameters
+                if(getMimetype() != null && getMimetype().length() > 0) {
+                    put.setRequestHeader(HEADER_CONTENT_TYPE, getMimetype());
+                }
+            }
+            // Set the content length
+            put.setRequestHeader(HEADER_CONTENT_LENGTH, Long.toString(put.getRequestEntity().getContentLength()));
+            return putBody.toString();
+        }
+        else {
+            return null;
+        }        
      }
 
 	// Implement locally, as current httpclient InputStreamRI implementation does not close file...

Modified: jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java?rev=584535&r1=584534&r2=584535&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java (original)
+++ jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java Sun Oct 14 05:46:26 2007
@@ -375,7 +375,7 @@
      *            The encoding used for the querystring parameter values
      */
     public void setPath(String path, String contentEncoding) {
-        if (GET.equals(getMethod())) {
+        if (GET.equals(getMethod()) || DELETE.equals(getMethod())) {
             int index = path.indexOf(QRY_PFX);
             if (index > -1) {
                 setProperty(PATH, path.substring(0, index));
@@ -529,6 +529,10 @@
 	public void addArgument(String name, String value, String metadata) {
 		this.getArguments().addArgument(new HTTPArgument(name, value, metadata));
 	}
+	
+	public boolean hasArguments() {
+		return getArguments().getArgumentCount() > 0;
+	}
 
 	public void addTestElement(TestElement el) {
 		if (el instanceof CookieManager) {
@@ -708,8 +712,8 @@
         }
         pathAndQuery.append(path);
 
-        // Add the query string if it is a HTTP GET request
-        if(GET.equals(getMethod())) {
+        // Add the query string if it is a HTTP GET or DELETE request
+        if(GET.equals(getMethod()) || DELETE.equals(getMethod())) {
             // Get the query string encoded in specified encoding
             // If no encoding is specified by user, we will get it
             // encoded in UTF-8, which is what the HTTP spec says
@@ -861,11 +865,18 @@
     }
 
 	public String toString() {
-		try {
-			return this.getUrl().toString() + ((POST.equals(getMethod())) ? "\nQuery Data: " + getQueryString() : "");
-		} catch (MalformedURLException e) {
-			return "";
-		}
+        try {
+            StringBuffer stringBuffer = new StringBuffer();
+            stringBuffer.append(this.getUrl().toString());
+            // Append body if it is a post or put
+            if(POST.equals(getMethod()) || PUT.equals(getMethod())) {
+                stringBuffer.append("\nQuery Data: ");
+                stringBuffer.append(getQueryString());
+            }
+            return stringBuffer.toString();
+        } catch (MalformedURLException e) {
+            return "";
+        }
 	}
 
 	/**
@@ -1293,7 +1304,7 @@
      * Method to tell if the request has any files to be uploaded
      */
     protected boolean hasUploadableFiles() {
-        return getFilename() != null && getFilename().length() > 0;        
+        return getFilename() != null && getFilename().trim().length() > 0;        
     }
 
     public static String[] getValidMethodsAsArray(){

Modified: jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/PostWriter.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/PostWriter.java?rev=584535&r1=584534&r2=584535&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/PostWriter.java (original)
+++ jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/PostWriter.java Sun Oct 14 05:46:26 2007
@@ -125,7 +125,7 @@
         }
         else {
             // If there are no arguments, we can send a file as the body of the request
-            if(sampler.getArguments() != null && sampler.getArguments().getArgumentCount() == 0 && sampler.getSendFileAsPostBody()) {
+            if(sampler.getArguments() != null && !sampler.hasArguments() && sampler.getSendFileAsPostBody()) {
                 OutputStream out = connection.getOutputStream();
                 writeFileToStream(sampler.getFilename(), out);
                 out.flush();
@@ -174,10 +174,14 @@
             PropertyIterator args = sampler.getArguments().iterator();
             while (args.hasNext()) {
                 HTTPArgument arg = (HTTPArgument) args.next().getObjectValue();
+                String parameterName = arg.getName();
+                if (parameterName.length()==0){
+                    continue; // Skip parameters with a blank name (allows use of optional variables in parameter lists)
+                }
                 // End the previous multipart
                 bos.write(CRLF);
                 // Write multipart for parameter
-                writeFormMultipart(bos, arg.getName(), arg.getValue(), contentEncoding);
+                writeFormMultipart(bos, parameterName, arg.getValue(), contentEncoding);
             }
             // If there are any files, we need to end the previous multipart
             if(sampler.hasUploadableFiles()) {



---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org