Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP Proxy XML-RPC support #1871

Closed
asfimport opened this issue Feb 26, 2007 · 9 comments
Closed

HTTP Proxy XML-RPC support #1871

asfimport opened this issue Feb 26, 2007 · 9 comments

Comments

@asfimport
Copy link
Collaborator

Jesper Thorhauge (Bug 41707):
JMeters http proxy does not record xml-rpc calls correctly. An xml-rpc call is
not posted in the usual name=value structure, but simply as one big chunk of
xml. I have made a patch which first of all check if the postdata is xml, by
using some very simple string comparison on the query string. If the postdata
seems to be xml, it is parsed as xml and checked against an un-official xml-rpc
xsd schema taken from ibiblio.org. If any error occurs or the xml-rpc cannot be
validated against the schema, the request is recorded the usual way.

This is my first patch for the jmeter project, so please bear with me.

OS: All

@asfimport
Copy link
Collaborator Author

Jesper Thorhauge (migrated from Bugzilla):
Created attachment HTTPSamplerBase.java: HTTPSamplerBase supporting xml-rpc recording.

HTTPSamplerBase.java
Index: src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
===================================================================
--- src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java	(revision 511863)
+++ src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jmeter.protocol.http.sampler;
 
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
@@ -52,6 +53,8 @@
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.jorphan.util.JOrphanUtils;
 import org.apache.log.Logger;
+import org.apache.xerces.parsers.DOMParser;
+import org.xml.sax.InputSource;
 
 /**
  * Common constants and methods for HTTP samplers
@@ -229,6 +232,10 @@
         }
     }
     
+    //variables used for xml-rpc call handling
+    public static DOMParser xmlRpcParser = null;
+    public static XmlRpcErrorHandler xmlRpcErrorHandler = null;
+    
     ////////////////////// Variables //////////////////////
     
     private boolean dynamicPath = false;// Set false if spaces are already encoded
@@ -396,6 +403,12 @@
 		this.getArguments().addArgument(arg);
 	}
 
+    public void addUnencodedArgument(String name, String value, String metadata) {
+        HTTPArgument arg = new HTTPArgument(name, value, metadata, false);
+        arg.setAlwaysEncoded(false);
+        this.getArguments().addArgument(arg);
+    }
+    
 	public void addArgument(String name, String value) {
 		this.getArguments().addArgument(new HTTPArgument(name, value));
 	}
@@ -618,40 +631,44 @@
 	 * 
 	 */
 	public void parseArguments(String queryString) {
-		String[] args = JOrphanUtils.split(queryString, QRY_SEP);
-		for (int i = 0; i < args.length; i++) {
-			// need to handle four cases: 
-            // - string contains name=value
-			// - string contains name=
-			// - string contains name
-			// - empty string
-            
-			String metaData; // records the existance of an equal sign
-            String name;
-            String value;
-            int length = args[i].length();
-            int endOfNameIndex = args[i].indexOf(ARG_VAL_SEP);
-            if (endOfNameIndex != -1) {// is there a separator?
-				// case of name=value, name=
-				metaData = ARG_VAL_SEP;
-                name = args[i].substring(0, endOfNameIndex);
-                value = args[i].substring(endOfNameIndex + 1, length);
-			} else {
-				metaData = "";
-                name=args[i];
-                value="";
-			}
-			if (name.length() > 0) {
-                // The browser has already done the encoding, so save the values as is 
-                HTTPArgument arg = new HTTPArgument(name, value, metaData, false);
-                // and make sure they stay that way:
-                arg.setAlwaysEncoded(false);
-                // Note that URL.encode()/decode() do not follow RFC3986 entirely
-				this.getArguments().addArgument(arg);
-				// TODO: this leaves the arguments in encoded form, which may be difficult to read
-                // if we can find proper coding methods, this could be tidied up 
-            }
-		}
+        if (isXmlRpc(queryString)) {
+            addUnencodedArgument("", queryString, "");
+        } else {      
+    		String[] args = JOrphanUtils.split(queryString, QRY_SEP);
+    		for (int i = 0; i < args.length; i++) {
+    			// need to handle four cases: 
+                // - string contains name=value
+    			// - string contains name=
+    			// - string contains name
+    			// - empty string
+                
+    			String metaData; // records the existance of an equal sign
+                String name;
+                String value;
+                int length = args[i].length();
+                int endOfNameIndex = args[i].indexOf(ARG_VAL_SEP);
+                if (endOfNameIndex != -1) {// is there a separator?
+    				// case of name=value, name=
+    				metaData = ARG_VAL_SEP;
+                    name = args[i].substring(0, endOfNameIndex);
+                    value = args[i].substring(endOfNameIndex + 1, length);
+    			} else {
+    				metaData = "";
+                    name=args[i];
+                    value="";
+    			}
+    			if (name.length() > 0) {
+                    // The browser has already done the encoding, so save the values as is 
+                    HTTPArgument arg = new HTTPArgument(name, value, metaData, false);
+                    // and make sure they stay that way:
+                    arg.setAlwaysEncoded(false);
+                    // Note that URL.encode()/decode() do not follow RFC3986 entirely
+    				this.getArguments().addArgument(arg);
+    				// TODO: this leaves the arguments in encoded form, which may be difficult to read
+                    // if we can find proper coding methods, this could be tidied up 
+                }
+    		}
+        }
 	}
 
 	public String toString() {
@@ -1009,5 +1026,33 @@
     public static boolean isSecure(URL url){
         return isSecure(url.getProtocol());
     }
+    
+    /**
+     * check for xmlrpc request using xsd from http://www.ibiblio.org/xml/books/xmljava/chapters/ch02s05.html (no official xsd exists)
+     * 
+     * @param queryString
+     * @return
+     */
+    private boolean isXmlRpc(String queryString) {
+      try {        
+        if (!queryString.startsWith("<?xml"))
+          return false;
+        
+        if (xmlRpcParser == null) {
+          xmlRpcParser = new DOMParser();
+          xmlRpcParser.setFeature("http://xml.org/sax/features/validation", true);
+          xmlRpcParser.setFeature("http://apache.org/xml/features/validation/schema", true);
+          xmlRpcParser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", "xml-rpc.xsd");        
+          xmlRpcErrorHandler = new XmlRpcErrorHandler();
+          xmlRpcParser.setErrorHandler(xmlRpcErrorHandler);
+        }
+        xmlRpcParser.parse(new InputSource(new ByteArrayInputStream(queryString.getBytes())));
+        return xmlRpcErrorHandler.getParseErrors().length == 0;
+      } catch (Exception e) {
+        log.debug("isXmlRpc() " + e);
+      }      
+      return false;
+    }
+    
 }
 

@asfimport
Copy link
Collaborator Author

Jesper Thorhauge (migrated from Bugzilla):
Created attachment XmlRpcErrorHandler.java: XmlRpcErrorHandler used for xsd schema checking of xml-rpc call

XmlRpcErrorHandler.java
Index: src/protocol/http/org/apache/jmeter/protocol/http/sampler/XmlRpcErrorHandler.java
===================================================================
--- src/protocol/http/org/apache/jmeter/protocol/http/sampler/XmlRpcErrorHandler.java	(revision 0)
+++ src/protocol/http/org/apache/jmeter/protocol/http/sampler/XmlRpcErrorHandler.java	(revision 0)
@@ -0,0 +1,24 @@
+package org.apache.jmeter.protocol.http.sampler;
+
+import java.util.Stack;
+
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class XmlRpcErrorHandler extends DefaultHandler {
+
+  private Stack parseErrors = null;
+  
+  public SAXParseException[] getParseErrors() {    
+    if (parseErrors == null)
+      parseErrors = new Stack();
+    return (SAXParseException[])parseErrors.toArray(new SAXParseException[0]);
+  }
+  
+  public void error(SAXParseException e) {
+    if (parseErrors == null)
+      parseErrors = new Stack();
+    parseErrors.push(e);
+  }
+  
+}

@asfimport
Copy link
Collaborator Author

Jesper Thorhauge (migrated from Bugzilla):
Created attachment xml-rpc.xsd: XML-RPC xsd schema (un-official)

xml-rpc.xsd
Index: bin/xml-rpc.xsd
===================================================================
--- bin/xml-rpc.xsd	(revision 0)
+++ bin/xml-rpc.xsd	(revision 0)
@@ -0,0 +1,132 @@
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+  <!-- The only two possible root elements are methodResponse and
+       methodCall so these are the only two I use a top-level
+       declaration for. --> 
+
+  <xsd:element name="methodCall">
+    <xsd:complexType>
+      <xsd:all>
+        <xsd:element name="methodName">
+          <xsd:simpleType>
+            <xsd:restriction base="ASCIIString">
+              <xsd:pattern value="([A-Za-z0-9]|/|\.|:|_)*" />
+            </xsd:restriction>
+          </xsd:simpleType>
+        </xsd:element>
+        <xsd:element name="params" minOccurs="0" maxOccurs="1">
+          <xsd:complexType>
+            <xsd:sequence>
+              <xsd:element name="param"  type="ParamType" 
+                           minOccurs="0" maxOccurs="unbounded"/>
+            </xsd:sequence>
+          </xsd:complexType>
+         </xsd:element>
+      </xsd:all>
+    </xsd:complexType>  
+  </xsd:element>
+
+  <xsd:element name="methodResponse">
+    <xsd:complexType>
+      <xsd:choice>
+        <xsd:element name="params">
+          <xsd:complexType>
+            <xsd:sequence>
+              <xsd:element name="param" type="ParamType"/>
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="fault">
+          <!-- What can appear inside a fault is very restricted -->
+          <xsd:complexType>
+            <xsd:sequence>
+              <xsd:element name="value">
+                <xsd:complexType>
+                  <xsd:sequence>
+                    <xsd:element name="struct"> 
+                      <xsd:complexType> 
+                        <xsd:sequence> 
+                          <xsd:element name="member" 
+                                       type="MemberType">
+                          </xsd:element>
+                          <xsd:element name="member" 
+                                       type="MemberType">
+                          </xsd:element>
+                        </xsd:sequence>
+                      </xsd:complexType>
+                    </xsd:element>
+                  </xsd:sequence>
+                </xsd:complexType>
+              </xsd:element>
+            </xsd:sequence>
+          </xsd:complexType>
+         </xsd:element>
+      </xsd:choice>
+    </xsd:complexType>  
+  </xsd:element>
+
+  <xsd:complexType name="ParamType">
+    <xsd:sequence>
+      <xsd:element name="value" type="ValueType"/>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="ValueType" mixed="true">
+    <!-- I need to figure out how to say that this
+         is either a simple xsd:string type or that 
+         it contains one of these elements; but that otherwise
+         it does not have mixed content -->
+    <xsd:choice>
+      <xsd:element name="i4"            type="xsd:int"/>
+      <xsd:element name="int"           type="xsd:int"/>
+      <xsd:element name="string"        type="ASCIIString"/>
+      <xsd:element name="double"        type="xsd:decimal"/>
+      <xsd:element name="Base64"        type="xsd:base64Binary"/>
+      <xsd:element name="boolean"       type="NumericBoolean"/>
+      <xsd:element name="dateTime.iso8601" type="xsd:dateTime"/>
+      <xsd:element name="array"         type="ArrayType"/>
+      <xsd:element name="struct"        type="StructType"/>
+    </xsd:choice>
+  </xsd:complexType>
+
+  <xsd:complexType name="StructType">
+    <xsd:sequence>
+      <xsd:element name="member" type="MemberType" 
+                   maxOccurs="unbounded"/>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="MemberType">
+    <xsd:sequence>
+      <xsd:element name="name"  type="xsd:string" />
+      <xsd:element name="value" type="ValueType"/>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="ArrayType">
+    <xsd:sequence>
+      <xsd:element name="data">
+        <xsd:complexType>
+          <xsd:sequence>
+            <xsd:element name="value"  type="ValueType" 
+                         minOccurs="0" maxOccurs="unbounded"/>
+          </xsd:sequence>
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:simpleType name="ASCIIString">
+    <xsd:restriction base="xsd:string">
+      <xsd:pattern value="([ -~]|\n|\r|\t)*" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="NumericBoolean">
+    <xsd:restriction base="xsd:boolean">
+      <xsd:pattern value="0|1" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+</xsd:schema>
\ No newline at end of file

@asfimport
Copy link
Collaborator Author

Jesper Thorhauge (migrated from Bugzilla):
Created attachment HTTPSamplerBase.java: HTTPSamplerBase supporting xml-rpc recording, cleaned up

HTTPSamplerBase.java
Index: src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
===================================================================
--- src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java	(revision 512300)
+++ src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.jmeter.protocol.http.sampler;
 
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
@@ -52,6 +53,11 @@
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.jorphan.util.JOrphanUtils;
 import org.apache.log.Logger;
+import org.apache.xerces.parsers.DOMParser;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
 
 /**
  * Common constants and methods for HTTP samplers
@@ -396,6 +402,12 @@
 		this.getArguments().addArgument(arg);
 	}
 
+    public void addUnencodedArgument(String name, String value, String metadata) {
+        HTTPArgument arg = new HTTPArgument(name, value, metadata, false);
+        arg.setAlwaysEncoded(false);
+        this.getArguments().addArgument(arg);
+    }
+    
 	public void addArgument(String name, String value) {
 		this.getArguments().addArgument(new HTTPArgument(name, value));
 	}
@@ -618,40 +630,44 @@
 	 * 
 	 */
 	public void parseArguments(String queryString) {
-		String[] args = JOrphanUtils.split(queryString, QRY_SEP);
-		for (int i = 0; i < args.length; i++) {
-			// need to handle four cases: 
-            // - string contains name=value
-			// - string contains name=
-			// - string contains name
-			// - empty string
-            
-			String metaData; // records the existance of an equal sign
-            String name;
-            String value;
-            int length = args[i].length();
-            int endOfNameIndex = args[i].indexOf(ARG_VAL_SEP);
-            if (endOfNameIndex != -1) {// is there a separator?
-				// case of name=value, name=
-				metaData = ARG_VAL_SEP;
-                name = args[i].substring(0, endOfNameIndex);
-                value = args[i].substring(endOfNameIndex + 1, length);
-			} else {
-				metaData = "";
-                name=args[i];
-                value="";
-			}
-			if (name.length() > 0) {
-                // The browser has already done the encoding, so save the values as is 
-                HTTPArgument arg = new HTTPArgument(name, value, metaData, false);
-                // and make sure they stay that way:
-                arg.setAlwaysEncoded(false);
-                // Note that URL.encode()/decode() do not follow RFC3986 entirely
-				this.getArguments().addArgument(arg);
-				// TODO: this leaves the arguments in encoded form, which may be difficult to read
-                // if we can find proper coding methods, this could be tidied up 
-            }
-		}
+        if (isXmlRpc(queryString)) {
+            addUnencodedArgument("", queryString, "");
+        } else {      
+    		String[] args = JOrphanUtils.split(queryString, QRY_SEP);
+    		for (int i = 0; i < args.length; i++) {
+    			// need to handle four cases: 
+                // - string contains name=value
+    			// - string contains name=
+    			// - string contains name
+    			// - empty string
+                
+    			String metaData; // records the existance of an equal sign
+                String name;
+                String value;
+                int length = args[i].length();
+                int endOfNameIndex = args[i].indexOf(ARG_VAL_SEP);
+                if (endOfNameIndex != -1) {// is there a separator?
+    				// case of name=value, name=
+    				metaData = ARG_VAL_SEP;
+                    name = args[i].substring(0, endOfNameIndex);
+                    value = args[i].substring(endOfNameIndex + 1, length);
+    			} else {
+    				metaData = "";
+                    name=args[i];
+                    value="";
+    			}
+    			if (name.length() > 0) {
+                    // The browser has already done the encoding, so save the values as is 
+                    HTTPArgument arg = new HTTPArgument(name, value, metaData, false);
+                    // and make sure they stay that way:
+                    arg.setAlwaysEncoded(false);
+                    // Note that URL.encode()/decode() do not follow RFC3986 entirely
+    				this.getArguments().addArgument(arg);
+    				// TODO: this leaves the arguments in encoded form, which may be difficult to read
+                    // if we can find proper coding methods, this could be tidied up 
+                }
+    		}
+        }
 	}
 
 	public String toString() {
@@ -1009,5 +1025,37 @@
     public static boolean isSecure(URL url){
         return isSecure(url.getProtocol());
     }
+    
+    /**
+     * Check for xmlrpc request using xsd from http://www.ibiblio.org/xml/books/xmljava/chapters/ch02s05.html (no official xsd exists)
+     * 
+     * @param queryString
+     * @return
+     */
+    private boolean isXmlRpc(String queryString) {
+      try {        
+        if (!queryString.startsWith("<?xml"))
+          return false;
+
+        DOMParser xmlRpcParser = new DOMParser();
+        xmlRpcParser.setFeature("http://xml.org/sax/features/validation", true);
+        xmlRpcParser.setFeature("http://apache.org/xml/features/validation/schema", true);
+        xmlRpcParser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", "xml-rpc.xsd");        
+        XmlRpcErrorHandler xmlRpcErrorHandler = new XmlRpcErrorHandler();
+        xmlRpcParser.setErrorHandler(xmlRpcErrorHandler);
+        xmlRpcParser.parse(new InputSource(new ByteArrayInputStream(queryString.getBytes())));
+        return xmlRpcErrorHandler.getParseErrors().length == 0;
+      } catch (SAXNotSupportedException snse) {
+        log.warn("isXmlRpc() " + snse);
+      } catch (SAXNotRecognizedException snre) {
+        log.warn("isXmlRpc() " + snre);
+      } catch (SAXException se) {
+        log.warn("isXmlRpc() " + se);
+      } catch (IOException ioe) {
+        log.warn("isXmlRpc() " + ioe);
+      }      
+      return false;
+    }
+    
 }
 

@asfimport
Copy link
Collaborator Author

Jesper Thorhauge (migrated from Bugzilla):
Created attachment XmlRpcErrorHandler.java: XmlRpcErrorHandler used for xsd schema checking of xml-rpc call

XmlRpcErrorHandler.java
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jmeter.protocol.http.sampler;

import java.util.Stack;

import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

public class XmlRpcErrorHandler extends DefaultHandler {

  private Stack parseErrors = null;
  
  public SAXParseException[] getParseErrors() {    
    if (parseErrors == null)
      parseErrors = new Stack();
    return (SAXParseException[])parseErrors.toArray(new SAXParseException[0]);
  }
  
  public void error(SAXParseException e) {
    if (parseErrors == null)
      parseErrors = new Stack();
    parseErrors.push(e);
  }
  
}

@asfimport
Copy link
Collaborator Author

Jesper Thorhauge (migrated from Bugzilla):
Created attachment xml-rpc.xsd: XML-RPC xsd schema (un-official)

xml-rpc.xsd
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <!-- The only two possible root elements are methodResponse and
       methodCall so these are the only two I use a top-level
       declaration for. --> 

  <xsd:element name="methodCall">
    <xsd:complexType>
      <xsd:all>
        <xsd:element name="methodName">
          <xsd:simpleType>
            <xsd:restriction base="ASCIIString">
              <xsd:pattern value="([A-Za-z0-9]|/|\.|:|_)*" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
        <xsd:element name="params" minOccurs="0" maxOccurs="1">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="param"  type="ParamType" 
                           minOccurs="0" maxOccurs="unbounded"/>
            </xsd:sequence>
          </xsd:complexType>
         </xsd:element>
      </xsd:all>
    </xsd:complexType>  
  </xsd:element>

  <xsd:element name="methodResponse">
    <xsd:complexType>
      <xsd:choice>
        <xsd:element name="params">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="param" type="ParamType"/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
        <xsd:element name="fault">
          <!-- What can appear inside a fault is very restricted -->
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="value">
                <xsd:complexType>
                  <xsd:sequence>
                    <xsd:element name="struct"> 
                      <xsd:complexType> 
                        <xsd:sequence> 
                          <xsd:element name="member" 
                                       type="MemberType">
                          </xsd:element>
                          <xsd:element name="member" 
                                       type="MemberType">
                          </xsd:element>
                        </xsd:sequence>
                      </xsd:complexType>
                    </xsd:element>
                  </xsd:sequence>
                </xsd:complexType>
              </xsd:element>
            </xsd:sequence>
          </xsd:complexType>
         </xsd:element>
      </xsd:choice>
    </xsd:complexType>  
  </xsd:element>

  <xsd:complexType name="ParamType">
    <xsd:sequence>
      <xsd:element name="value" type="ValueType"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="ValueType" mixed="true">
    <!-- I need to figure out how to say that this
         is either a simple xsd:string type or that 
         it contains one of these elements; but that otherwise
         it does not have mixed content -->
    <xsd:choice>
      <xsd:element name="i4"            type="xsd:int"/>
      <xsd:element name="int"           type="xsd:int"/>
      <xsd:element name="string"        type="ASCIIString"/>
      <xsd:element name="double"        type="xsd:decimal"/>
      <xsd:element name="Base64"        type="xsd:base64Binary"/>
      <xsd:element name="boolean"       type="NumericBoolean"/>
      <xsd:element name="dateTime.iso8601" type="xsd:dateTime"/>
      <xsd:element name="array"         type="ArrayType"/>
      <xsd:element name="struct"        type="StructType"/>
    </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="StructType">
    <xsd:sequence>
      <xsd:element name="member" type="MemberType" 
                   maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="MemberType">
    <xsd:sequence>
      <xsd:element name="name"  type="xsd:string" />
      <xsd:element name="value" type="ValueType"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="ArrayType">
    <xsd:sequence>
      <xsd:element name="data">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="value"  type="ValueType" 
                         minOccurs="0" maxOccurs="unbounded"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:simpleType name="ASCIIString">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="([ -~]|\n|\r|\t)*" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="NumericBoolean">
    <xsd:restriction base="xsd:boolean">
      <xsd:pattern value="0|1" />
    </xsd:restriction>
  </xsd:simpleType>

</xsd:schema>````

</details>

@asfimport
Copy link
Collaborator Author

Jesper Thorhauge (migrated from Bugzilla):
This version should not affect any other classes using the parseArguments
method, as last patch did.

Created attachment HTTPSamplerBase.java: HTTPSamplerBase supporting xml-rpc and other not-"name=value" postdata.

HTTPSamplerBase.java
Index: src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
===================================================================
--- src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java	(revision 513802)
+++ src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java	(working copy)
@@ -395,7 +395,13 @@
 		}
 		this.getArguments().addArgument(arg);
 	}
-
+    
+    public void addNonEncodedArgument(String name, String value, String metadata) {
+        HTTPArgument arg = new HTTPArgument(name, value, metadata, false);
+        arg.setAlwaysEncoded(false);
+        this.getArguments().addArgument(arg);
+    }
+    
 	public void addArgument(String name, String value) {
 		this.getArguments().addArgument(new HTTPArgument(name, value));
 	}

@asfimport
Copy link
Collaborator Author

Jesper Thorhauge (migrated from Bugzilla):
Created attachment HttpRequestHdr.java: As commented by sebb, the fix should go into HttpRequestHdr.java instead of httpsamplerbase

HttpRequestHdr.java
Index: src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpRequestHdr.java
===================================================================
--- src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpRequestHdr.java	(revision 513802)
+++ src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpRequestHdr.java	(working copy)
@@ -246,8 +246,10 @@
 			sampler.setFileField(urlConfig.getFileFieldName());
 			sampler.setFilename(urlConfig.getFilename());
 			sampler.setMimetype(urlConfig.getMimeType());
+        } else if (postData != null && postData.trim().startsWith("<?")) {
+            sampler.addNonEncodedArgument("", postData, ""); //used when postData is pure xml (ex. an xml-rpc call)
 		} else {
-			sampler.parseArguments(postData);
+			sampler.parseArguments(postData); //standard name=value postData
 		}
         if (log.isDebugEnabled())
     		log.debug("sampler path = " + sampler.getPath());

@asfimport
Copy link
Collaborator Author

Sebb (migrated from Bugzilla):
Thanks!

Now fixed in SVN.

It will be in the next release and the next nightly build at:

http://people.apache.org/builds/jakarta-jmeter/nightly/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant