You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2019/07/22 18:49:45 UTC
[jmeter] branch master updated: Support all cURL command line
options and allow import of multiple commands from a file (Fix bugs 63452 &
63419) (#475)
This is an automated email from the ASF dual-hosted git repository.
pmouawad pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git
The following commit(s) were added to refs/heads/master by this push:
new 9869daa Support all cURL command line options and allow import of multiple commands from a file (Fix bugs 63452 & 63419) (#475)
9869daa is described below
commit 9869daa3ec2d558b7900d2c4e8b4f396e72c8750
Author: UBIK LOAD PACK <su...@ubikloadpack.com>
AuthorDate: Mon Jul 22 20:49:39 2019 +0200
Support all cURL command line options and allow import of multiple commands from a file (Fix bugs 63452 & 63419) (#475)
This Implements Features :
- https://bz.apache.org/bugzilla/show_bug.cgi?id=63452
- https://bz.apache.org/bugzilla/show_bug.cgi?id=63419
Contributed by UbikLoadPack Team
---
.../apache/jmeter/resources/messages.properties | 10 +-
.../apache/jmeter/resources/messages_fr.properties | 10 +-
.../jmeter/protocol/http/curl/BasicCurlParser.java | 893 ++++++++++++++++++++-
.../http/gui/action/ParseCurlCommandAction.java | 711 +++++++++++++---
.../protocol/http/sampler/HTTPSamplerBase.java | 54 +-
.../apache/jmeter/curl/BasicCurlParserTest.java | 550 ++++++++++++-
.../gui/action/ParseCurlCommandActionTest.java | 605 ++++++++++++++
xdocs/changes.xml | 2 +
xdocs/images/screenshots/curl/choose_curl.png | Bin 0 -> 51481 bytes
xdocs/images/screenshots/curl/enter_command.png | Bin 0 -> 37985 bytes
.../screenshots/curl/enter_command_from_file.png | Bin 0 -> 28676 bytes
.../screenshots/curl/http_request_warning.png | Bin 0 -> 147029 bytes
xdocs/images/screenshots/curl/result.png | Bin 0 -> 183303 bytes
xdocs/usermanual/curl.xml | 126 +++
xdocs/usermanual/glossary.xml | 2 +-
xdocs/usermanual/history_future.xml | 4 +-
xdocs/usermanual/index.xml | 13 +-
17 files changed, 2805 insertions(+), 175 deletions(-)
diff --git a/src/core/org/apache/jmeter/resources/messages.properties b/src/core/org/apache/jmeter/resources/messages.properties
index 63e93bf..65aa2b4 100644
--- a/src/core/org/apache/jmeter/resources/messages.properties
+++ b/src/core/org/apache/jmeter/resources/messages.properties
@@ -249,10 +249,12 @@ cssjquery_tester_field=Selector\:
cssjquery_tester_title=CSS Selector Tester
csvread_file_file_name=CSV file to get values from | *alias
curl_create_failure=Error creating HTTP Request, error:{0}
-curl_create_request=Create HTTP Request
-curl_create_success=Successfully created HTTP Request
-curl_import=Create HTTP Request from cURL
-curl_import_menu=Import from cURL (alpha)
+curl_create_request=Create Test Plan
+curl_create_success=Successfully created HTTP Request(s)
+curl_import=Create Test Plan from cURL
+curl_import_from_file=Read cURL commands from file
+curl_add_cookie_header_to_cookiemanager=Add cookie header to Cookie Manager
+curl_import_menu=Import from cURL
cut=Cut
cut_paste_function=Function syntax\:
database_conn_pool_max_usage=Max Usage For Each Connection\:
diff --git a/src/core/org/apache/jmeter/resources/messages_fr.properties b/src/core/org/apache/jmeter/resources/messages_fr.properties
index ec03294..f4e6d65 100644
--- a/src/core/org/apache/jmeter/resources/messages_fr.properties
+++ b/src/core/org/apache/jmeter/resources/messages_fr.properties
@@ -244,10 +244,12 @@ cssjquery_tester_field=Sélecteur\:
cssjquery_tester_title=Testeur Selecteur CSS
csvread_file_file_name=Fichier CSV pour obtenir les valeurs de | *alias
curl_create_failure=Erreur de création de la requête HTTP, erreur:{0}.
-curl_create_request=Créer une requête HTTP
-curl_create_success=Requête HTTP créée avec succès
-curl_import=Créer une requête HTTP à partir de cURL
-curl_import_menu=Importer de cURL (alpha)
+curl_create_request=Créer un Plan de Test
+curl_import_from_file=Lire les commandes cURL du fichier
+curl_add_cookie_header_to_cookiemanager=Ajouter cookie header au Cookie Manager
+curl_create_success=Requête HTTP créée(s) avec succès
+curl_import=Créer un Plan de Test à partir de commandes cURL
+curl_import_menu=Importer de cURL
cut=Couper
cut_paste_function=Syntaxe de la fonction \:
database_conn_pool_max_usage=Utilisation max pour chaque connexion\:
diff --git a/src/protocol/http/org/apache/jmeter/protocol/http/curl/BasicCurlParser.java b/src/protocol/http/org/apache/jmeter/protocol/http/curl/BasicCurlParser.java
index f92e267..6471848 100644
--- a/src/protocol/http/org/apache/jmeter/protocol/http/curl/BasicCurlParser.java
+++ b/src/protocol/http/org/apache/jmeter/protocol/http/curl/BasicCurlParser.java
@@ -18,30 +18,103 @@
package org.apache.jmeter.protocol.http.curl;
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.apache.commons.cli.avalon.CLArgsParser;
import org.apache.commons.cli.avalon.CLOption;
import org.apache.commons.cli.avalon.CLOptionDescriptor;
+import org.apache.commons.io.FileUtils;
+import org.apache.jmeter.protocol.http.control.AuthManager.Mechanism;
+import org.apache.jmeter.protocol.http.control.Authorization;
+import org.apache.jmeter.protocol.http.control.Cookie;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Basic cURL command parser that handles:
- * -X
- * -H
- * --compressed
- * --data POST with Body data
*
* @since 5.1
*/
public class BasicCurlParser {
+ private static final Logger LOGGER = LoggerFactory.getLogger(BasicCurlParser.class);
private static final int METHOD_OPT = 'X';
private static final int COMPRESSED_OPT = 'c';// $NON-NLS-1$
private static final int HEADER_OPT = 'H';// $NON-NLS-1$
private static final int DATA_OPT = 'd';// $NON-NLS-1$
+ private static final int DATA_ASCII_OPT = "data-ascii".hashCode();// $NON-NLS-1$
+ private static final int DATA_BINARY_OPT = "data-binary".hashCode();// NOSONAR
+ private static final int DATA_URLENCODE_OPT = "data-urlencode".hashCode();// NOSONAR
+ private static final int DATA_RAW_OPT = "data-raw".hashCode();// NOSONAR
+ private static final int FORM_OPT = 'F';// $NON-NLS-1$
+ private static final int FORM_STRING_OPT = "form".hashCode();// $NON-NLS-1$
+ private static final int USER_AGENT_OPT = 'A';// $NON-NLS-1$
+ private static final int CONNECT_TIMEOUT_OPT = "connect-timeout".hashCode();// $NON-NLS-1$
+ private static final int COOKIE_OPT = 'b';// $NON-NLS-1$
+ private static final int USER_OPT = 'u';// $NON-NLS-1$
+ private static final int BASIC_OPT = "basic".hashCode();// NOSONAR
+ private static final int DIGEST_OPT = "digest".hashCode();// NOSONAR
+ private static final int CERT_OPT = 'E';// $NON-NLS-1$
+ private static final int CAFILE_OPT = "cacert".hashCode();// $NON-NLS-1$
+ private static final int CAPATH_OPT = "capath".hashCode();// $NON-NLS-1$
+ private static final int CIPHERS_OPT = "ciphers".hashCode();// $NON-NLS
+ private static final int CERT_STATUS_OPT = "cert-status".hashCode();// $NON-NLS-1$-1$
+ private static final int CERT_TYPE_OPT = "cert-type".hashCode();// $NON-NLS-1$-1$
+ private static final int KEY_OPT = "key".hashCode();// $NON-NLS-1$-1$
+ private static final int KEY_TYPE_OPT = "key-type".hashCode();// $NON-NLS-1$-1$
+ private static final int GET_OPT = 'G';// $NON-NLS-1$
+ private static final int DNS_OPT = "dns-servers".hashCode();// $NON-NLS-1$
+ private static final int NO_KEEPALIVE_OPT = "no-keepalive".hashCode();// $NON-NLS-1$
+ private static final int REFERER_OPT = 'e';// $NON-NLS-1$
+ private static final int LOCATION_OPT = 'L';// $NON-NLS-1$
+ private static final int INCLUDE_OPT = 'i';// $NON-NLS-1$
+ private static final int HEAD_OPT = 'I';// $NON-NLS-1$
+ private static final int PROXY_OPT = 'x';// $NON-NLS-1$
+ private static final int PROXY_USER_OPT = 'U';// $NON-NLS-1$
+ private static final int PROXY_NTLM_OPT = "proxy-ntlm".hashCode();// $NON-NLS-1$
+ private static final int PROXY_NEGOTIATE_OPT = "proxy-negotiate".hashCode();// $NON-NLS-1$
+ private static final int KEEPALIVETILE_OPT = "keepalive-time".hashCode();// $NON-NLS-1$
+ private static final int MAX_TIME_OPT = 'm';// $NON-NLS-1$
+ private static final int OUTPUT_OPT = 'o';// $NON-NLS-1$
+ private static final int CREATE_DIRS_OPT = "create-dir".hashCode();// $NON-NLS-1$
+ private static final int INSECURE_OPT = 'k';// $NON-NLS-1$
+ private static final int RAW_OPT = "raw".hashCode();// $NON-NLS-1$
+ private static final int INTERFACE_OPT = "interface".hashCode();// $NON-NLS-1$
+ private static final int DNS_RESOLVER_OPT = "resolve".hashCode();// $NON-NLS-1$
+ private static final int LIMIT_RATE_OPT = "limit-rate".hashCode();// $NON-NLS-1$
+ private static final int MAX_REDIRS_OPT = "max-redirs".hashCode();// $NON-NLS-1$
+ private static final int NOPROXY_OPT = "noproxy".hashCode();// $NON-NLS-1$
+ private static final List<Integer> AUTH_OPT = Arrays.asList(BASIC_OPT, DIGEST_OPT);// $NON-NLS-1$
+ private static final List<Integer> SSL_OPT = Arrays.asList(CAFILE_OPT, CAPATH_OPT, CERT_OPT, CIPHERS_OPT,
+ CERT_STATUS_OPT, CERT_TYPE_OPT, KEY_OPT, KEY_TYPE_OPT);// $NON-NLS-1$
+ private static final List<Integer> DATAS_OPT = Arrays.asList(DATA_OPT, DATA_ASCII_OPT, DATA_BINARY_OPT,
+ DATA_URLENCODE_OPT, DATA_RAW_OPT);// $NON-NLS-1$
+ private static final List<Integer> FORMS_OPT = Arrays.asList(FORM_OPT, FORM_STRING_OPT);// $NON-NLS-1$
+ private static final List<Integer> IGNORE_OPTIONS_OPT = Arrays.asList(OUTPUT_OPT, CREATE_DIRS_OPT, RAW_OPT,
+ INCLUDE_OPT, KEEPALIVETILE_OPT);// $NON-NLS-1$
+ private static final List<Integer> NOSUPPORT_OPTIONS_OPT = Arrays.asList(PROXY_NTLM_OPT, PROXY_NEGOTIATE_OPT);// $NON-NLS-1$
+ private static final List<Integer> PROPERTIES_OPT = Arrays.asList(MAX_REDIRS_OPT);// $NON-NLS-1$
+ private static final List<String> DYNAMIC_COOKIES = Arrays.asList("PHPSESSID", "JSESSIONID", "ASPSESSIONID",
+ "connect.sid");// $NON-NLS-1$
public static final class Request {
private boolean compressed;
@@ -49,17 +122,66 @@ public class BasicCurlParser {
private Map<String, String> headers = new LinkedHashMap<>();
private String method = "GET";
private String postData;
- /**
- */
+ private String interfaceName;
+ private double connectTimeout = -1;
+ private String cookies = "";
+ private String cookieInHeaders = "";
+ private String filepathCookie="";
+ private Authorization authorization = new Authorization();
+ private String caCert = "";
+ private Map<String, String> formData = new LinkedHashMap<>();
+ private Map<String, String> formStringData = new LinkedHashMap<>();
+ private Set<String> dnsServers = new HashSet<>();
+ private boolean isKeepAlive = true;
+ private double maxTime = -1;
+ private List<String> optionsIgnored = new ArrayList<>();
+ private List<String> optionsNoSupport = new ArrayList<>();
+ private List<String> optionsInProperties = new ArrayList<>();
+ private Map<String, String> proxyServer = new LinkedHashMap<>();
+ private String dnsResolver;
+ private int limitRate = 0;
+ private String noproxy;
+ private static final List<String> HEADERS_TO_IGNORE = Arrays.asList("Connection", "Host");// $NON-NLS-1$
+ private static final int ONE_KILOBYTE_IN_CPS = 1024;
public Request() {
super();
}
+
+ /**
+ * @return the HTTP method
+ */
+ public String getMethod() {
+ return method;
+ }
+
+ /**
+ * @param method the HTTP method to set
+ */
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ /**
+ * @param value the post data
+ */
+ public void setPostData(String value) {
+ this.postData = value;
+ }
+
+ /**
+ * @return the postData
+ */
+ public String getPostData() {
+ return postData;
+ }
+
/**
* @return the compressed
*/
public boolean isCompressed() {
return compressed;
}
+
/**
* @param compressed the compressed to set
*/
@@ -67,8 +189,30 @@ public class BasicCurlParser {
this.compressed = compressed;
}
+ /**
+ * @param name the field of Header
+ * @param value the value of Header
+ */
public void addHeader(String name, String value) {
- headers.put(name, value);
+ if ("COOKIE".equalsIgnoreCase(name)) {
+ this.cookieInHeaders = value;
+ } else if (!HEADERS_TO_IGNORE.contains(name)) {
+ headers.put(name, value);
+ }
+ }
+
+ /**
+ * @return the cookieInHeaders
+ */
+ public List<Cookie> getCookieInHeaders(String url) {
+ return Collections.unmodifiableList(stringToCookie(cookieInHeaders, url));
+ }
+
+ /**
+ * @param cookieInHeaders the cookieInHeaders to set
+ */
+ public void setCookieInHeaders(String cookieInHeaders) {
+ this.cookieInHeaders = cookieInHeaders;
}
/**
* @return the url
@@ -76,18 +220,287 @@ public class BasicCurlParser {
public String getUrl() {
return url;
}
+
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
+
/**
* @return the headers
*/
public Map<String, String> getHeaders() {
- return headers;
+ return Collections.unmodifiableMap(this.headers);
+ }
+
+ /**
+ * @return the list of options which are ignored
+ */
+ public List<String> getOptionsInProperties() {
+ return Collections.unmodifiableList(this.optionsInProperties);
+ }
+
+ /**
+ * @param option the option
+ */
+ public void addOptionsInProperties(String option) {
+ this.optionsInProperties.add(option);
+ }
+
+ /**
+ * @return the maximum transfer rate
+ */
+ public int getLimitRate() {
+ return limitRate;
+ }
+
+ /**
+ * Tranform the bandwidth to cps value (byte/s), cps =
+ * bandwidth*1024/8, the unit of bandwidth in JMeter is measured in kbit/s. And
+ * the speed in Curl is measured in bytes/second, so the conversion formula is
+ * cps=limitRate*1024
+ * @param limitRate the maximum transfer rate
+ */
+ public void setLimitRate(String limitRate) {
+ String unit = limitRate.substring(limitRate.length() - 1, limitRate.length()).toLowerCase();
+ int value = Integer.parseInt(limitRate.substring(0, limitRate.length() - 1).toLowerCase());
+ switch (unit) {
+ case "k":
+ this.limitRate = value * ONE_KILOBYTE_IN_CPS;
+ break;
+ case "m":
+ this.limitRate = value * ONE_KILOBYTE_IN_CPS * 1000;
+ break;
+ case "g":
+ this.limitRate = value * ONE_KILOBYTE_IN_CPS * 1000000;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * @return this list of hosts which don't use proxy
+ */
+ public String getNoproxy() {
+ return noproxy;
+ }
+
+ /**
+ * Set the list of hosts which don't use proxy
+ * @param noproxy
+ */
+ public void setNoproxy(String noproxy) {
+ this.noproxy = noproxy;
+ }
+
+ /**
+ * @return the DNS resolver
+ */
+ public String getDnsResolver() {
+ return dnsResolver;
+ }
+
+ /**
+ * set DNS resolver
+ * @param dnsResolver
+ */
+ public void setDnsResolver(String dnsResolver) {
+ this.dnsResolver = dnsResolver;
+ }
+
+ /**
+ * @return the interface name to perform an operation
+ */
+ public String getInterfaceName() {
+ return interfaceName;
+ }
+
+ /**
+ * @param interfaceName the name of interface
+ */
+ public void setInterfaceName(String interfaceName) {
+ this.interfaceName = interfaceName;
+ }
+
+ /**
+ * @return the list of options which are ignored
+ */
+ public List<String> getOptionsIgnored() {
+ return Collections.unmodifiableList(this.optionsIgnored);
+ }
+
+ /**
+ * @param option option is ignored
+ */
+ public void addOptionsIgnored(String option) {
+ this.optionsIgnored.add(option);
+ }
+
+ /**
+ * @return the list of options which are not supported by JMeter
+ */
+ public List<String> getOptionsNoSupport() {
+ return Collections.unmodifiableList(this.optionsNoSupport);
+ }
+
+ /**
+ * @param option option is not supported
+ */
+ public void addOptionsNoSupport(String option) {
+ this.optionsNoSupport.add(option);
+ }
+ /**
+ * @return the map of proxy server
+ */
+ public Map<String, String> getProxyServer() {
+ return Collections.unmodifiableMap(this.proxyServer);
+ }
+
+ /**
+ * @param proxyServer set the map of proxy server
+ */
+ public void setProxyServer(String key, String value) {
+ this.proxyServer.put(key, value);
+ }
+
+ /**
+ * @return if the Http request keeps alive
+ */
+ public boolean isKeepAlive() {
+ return isKeepAlive;
+ }
+
+ /**
+ * @param isKeepAlive set if the Http request keeps alive
+ */
+ public void setKeepAlive(boolean isKeepAlive) {
+ this.isKeepAlive = isKeepAlive;
+ }
+
+ /**
+ * @return the list of DNS server
+ */
+ public Set<String> getDnsServers() {
+ return Collections.unmodifiableSet(this.dnsServers);
+ }
+
+ /**
+ * @param dnsServer set the list of DNS server
+ */
+ public void addDnsServers(String dnsServer) {
+ this.dnsServers.add(dnsServer);
+ }
+
+ /**
+ * @return the map of form data
+ */
+ public Map<String, String> getFormStringData() {
+ return Collections.unmodifiableMap(this.formStringData);
+ }
+
+ /**
+ * @param key the key of form data
+ * @param value the value of form data
+ */
+ public void addFormStringData(String key, String value) {
+ formStringData.put(key, value);
+ }
+
+ /**
+ * @return the map of form data
+ */
+ public Map<String, String> getFormData() {
+ return Collections.unmodifiableMap(this.formData);
+ }
+
+ /**
+ * @param key the key of form data
+ * @param value the value of form data
+ */
+ public void addFormData(String key, String value) {
+ formData.put(key, value);
+ }
+
+ /**
+ * @return the certificate of the CA
+ */
+ public String getCaCert() {
+ return caCert;
+ }
+
+ /**
+ * the options which work for SSL
+ * @param caCert
+ */
+ public void setCacert(String caCert) {
+ this.caCert = caCert;
+ }
+
+ /**
+ * @return the authorization
+ */
+ public Authorization getAuthorization() {
+ return authorization;
}
+
+ /**
+ * @return the connection time out
+ */
+ public double getConnectTimeout() {
+ return connectTimeout;
+ }
+ /**
+ * @param connectTimeout the connection time out
+ */
+ public void setConnectTimeout(double connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
+
+ /**
+ * @return the max time of connection
+ */
+ public double getMaxTime() {
+ return maxTime;
+ }
+
+ /**
+ * @param the max time of connection
+ */
+ public void setMaxTime(double maxTime) {
+ this.maxTime = maxTime;
+ }
+
+ /**
+ * @return the filepathCookie
+ */
+ public String getFilepathCookie() {
+ return filepathCookie;
+ }
+
+ /**
+ * @param filepathCookie the filepathCookie to set
+ */
+ public void setFilepathCookie(String filepathCookie) {
+ this.filepathCookie = filepathCookie;
+ }
+
+ /**
+ * @return the cookies
+ */
+ public List<Cookie> getCookies(String url) {
+ return Collections.unmodifiableList(stringToCookie(cookies, url));
+ }
+
+ /**
+ * @param cookies the cookies to set
+ */
+ public void setCookies(String cookies) {
+ this.cookies = cookies;
+ }
+
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@@ -105,24 +518,6 @@ public class BasicCurlParser {
builder.append("]");
return builder.toString();
}
- public String getMethod() {
- return method;
- }
- /**
- * @param method the method to set
- */
- public void setMethod(String method) {
- this.method = method;
- }
- public void setPostData(String value) {
- this.postData = value;
- }
- /**
- * @return the postData
- */
- public String getPostData() {
- return postData;
- }
}
private static final CLOptionDescriptor D_COMPRESSED_OPT =
new CLOptionDescriptor("compressed", CLOptionDescriptor.ARGUMENT_DISALLOWED, COMPRESSED_OPT,
@@ -136,32 +531,144 @@ public class BasicCurlParser {
private static final CLOptionDescriptor D_DATA_OPT =
new CLOptionDescriptor("data", CLOptionDescriptor.ARGUMENT_REQUIRED, DATA_OPT,
"HTTP POST data");
+ private static final CLOptionDescriptor D_DATA_ASCII_OPT = new CLOptionDescriptor("data-ascii",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, DATA_ASCII_OPT, "HTTP POST ascii data ");
+ private static final CLOptionDescriptor D_DATA_BINARY_OPT = new CLOptionDescriptor("data-binary",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, DATA_BINARY_OPT, "HTTP POST binary data ");
+ private static final CLOptionDescriptor D_DATA_URLENCODE_OPT = new CLOptionDescriptor("data-urlencode",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, DATA_URLENCODE_OPT, "HTTP POST url encoding data ");
+ private static final CLOptionDescriptor D_DATA_RAW_OPT = new CLOptionDescriptor("data-raw",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, DATA_RAW_OPT, "HTTP POST url allowed '@' ");
+ private static final CLOptionDescriptor D_FORM_OPT = new CLOptionDescriptor("form",
+ CLOptionDescriptor.ARGUMENT_REQUIRED | CLOptionDescriptor.DUPLICATES_ALLOWED, FORM_OPT,
+ "HTTP POST form data allowed '@' and ';Type='");
+ private static final CLOptionDescriptor D_FORM_STRING_OPT = new CLOptionDescriptor("form-string",
+ CLOptionDescriptor.ARGUMENT_REQUIRED | CLOptionDescriptor.DUPLICATES_ALLOWED, FORM_STRING_OPT,
+ "HTTP POST form data ");
+ private static final CLOptionDescriptor D_USER_AGENT_OPT = new CLOptionDescriptor("user-agent",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, USER_AGENT_OPT, "The User-Agent string");
+ private static final CLOptionDescriptor D_CONNECT_TIMEOUT_OPT = new CLOptionDescriptor("connect-timeout",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, CONNECT_TIMEOUT_OPT,
+ "Maximum time in seconds that the connection to the server");
+ private static final CLOptionDescriptor D_REFERER_OPT = new CLOptionDescriptor("referer",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, REFERER_OPT,
+ "Sends the 'Referer Page' information to the HTTP server ");
+ private static final CLOptionDescriptor D_COOKIE_OPT = new CLOptionDescriptor("cookie",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, COOKIE_OPT, "Pass the data to the HTTP server as a cookie");
+ private static final CLOptionDescriptor D_USER_OPT = new CLOptionDescriptor("user",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, USER_OPT, "User and password to use for server authentication. ");
+ private static final CLOptionDescriptor D_BASIC_OPT = new CLOptionDescriptor("basic",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, BASIC_OPT, "HTTP Basic authentication ");
+ private static final CLOptionDescriptor D_DIGEST_OPT = new CLOptionDescriptor("digest",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, DIGEST_OPT, "HTTP digest authentication ");
+ private static final CLOptionDescriptor D_CERT_OPT = new CLOptionDescriptor("cert",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, CERT_OPT, " The specified client certificate file for SSL");
+ private static final CLOptionDescriptor D_CACERT_OPT = new CLOptionDescriptor("cacert",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, CAFILE_OPT,
+ "Use the specified certificate file to verify the peer. ");
+ private static final CLOptionDescriptor D_CAPATH_OPT = new CLOptionDescriptor("capath",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, CAPATH_OPT,
+ "Use the specified certificate directory to verify the peer. ");
+ private static final CLOptionDescriptor D_CIPHERS_OPT = new CLOptionDescriptor("ciphers",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, CIPHERS_OPT, "The ciphers to use in the connection. ");
+ private static final CLOptionDescriptor D_CERT_STATUS_OPT = new CLOptionDescriptor("cert-status",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, CERT_STATUS_OPT, "Tells curl to verify the status of the server "
+ + "certificate by using the Certificate Status Request TLS extension. ");
+ private static final CLOptionDescriptor D_CERT_TYPE_OPT = new CLOptionDescriptor("cert-type",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, CERT_TYPE_OPT, "Tells curl the type of certificate type of the "
+ + "provided certificate. PEM, DER and ENG are recognized types ");
+ private static final CLOptionDescriptor D_KEY_OPT = new CLOptionDescriptor("key",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, KEY_OPT,
+ "Private key file name. Allows you to provide your private key in this separate file. ");
+ private static final CLOptionDescriptor D_KEY_TYPE_OPT = new CLOptionDescriptor("key-type",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, KEY_TYPE_OPT,
+ "Private key file type. Specify which type your --key provided private key is.");
+ private static final CLOptionDescriptor D_GET_OPT = new CLOptionDescriptor("get",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, GET_OPT,
+ "Put the post data in the url and use get to replace post. ");
+ private static final CLOptionDescriptor D_DNS_SERVERS_OPT = new CLOptionDescriptor("dns-servers",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, DNS_OPT, "Resolve host name over DOH. ");
+ private static final CLOptionDescriptor D_NO_KEEPALIVE_OPT = new CLOptionDescriptor("no-keepalive",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, NO_KEEPALIVE_OPT, "Disabled keep-alive ");
+ private static final CLOptionDescriptor D_LOCATION_OPT = new CLOptionDescriptor("location",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, LOCATION_OPT, "Follow Redirect ");
+ private static final CLOptionDescriptor D_INCLUDE_OPT = new CLOptionDescriptor("include",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, INCLUDE_OPT, "Include the HTTP-header in the output ");
+ private static final CLOptionDescriptor D_HEAD_OPT = new CLOptionDescriptor("head",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, HEAD_OPT, "Fetch the HTTP-header only");
+ private static final CLOptionDescriptor D_INSECURE_OPT = new CLOptionDescriptor("insecure",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, INSECURE_OPT,
+ "Allows curl to perform insecure SSL connections and transfers");
+ private static final CLOptionDescriptor D_PROXY_OPT = new CLOptionDescriptor("proxy",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, PROXY_OPT,
+ "Use the specified HTTP proxy. If the port number" + " is not specified, it is assumed at port 1080.");
+ private static final CLOptionDescriptor D_PROXY_USER_OPT = new CLOptionDescriptor("proxy-user",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, PROXY_USER_OPT,
+ "Specify user and password to use for proxy authentication.");
+ private static final CLOptionDescriptor D_PROXY_NTLM_OPT = new CLOptionDescriptor("proxy-ntlm",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, PROXY_NTLM_OPT,
+ "Tells curl to use HTTP ntlm authentication when communicating with the given proxy. ");
+ private static final CLOptionDescriptor D_PROXY_NEGOTIATE_OPT = new CLOptionDescriptor("proxy-negotiate",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, PROXY_NEGOTIATE_OPT,
+ "Tells curl to use HTTP negotiate authentication when communicating with the given proxy. ");
+ private static final CLOptionDescriptor D_KEEPALIVETILE_OPT = new CLOptionDescriptor("keepalive-time",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, KEEPALIVETILE_OPT,
+ " This option sets the time a connection needs to remain idle before sending"
+ + " keepalive probes and the time between individual keepalive probes..");
+ private static final CLOptionDescriptor D_MAX_TIME_OPT = new CLOptionDescriptor("max-time",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, MAX_TIME_OPT,
+ "Maximum time in seconds that you allow the whole operation to take. ");
+ private static final CLOptionDescriptor D_OUTPUT_OPT = new CLOptionDescriptor("output",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, OUTPUT_OPT, "Write result to a file");
+ private static final CLOptionDescriptor D_CREATE_DIRS_OPT = new CLOptionDescriptor("create-dir",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, CREATE_DIRS_OPT,
+ "Create the necessary local directory hierarchy as needed for output file");
+ private static final CLOptionDescriptor D_RAW_OPT = new CLOptionDescriptor("raw",
+ CLOptionDescriptor.ARGUMENT_DISALLOWED, RAW_OPT,
+ "When used, it disables all internal HTTP decoding of content or transfer encodings "
+ + "and instead makes them passed on unaltered raw. ");
+ private static final CLOptionDescriptor D_INTERFACE_OPT = new CLOptionDescriptor("interface",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, INTERFACE_OPT, "Perform an operation using a specified interface");
+ private static final CLOptionDescriptor D_DNS_RESOLVER_OPT = new CLOptionDescriptor("resolve",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, DNS_RESOLVER_OPT,
+ "Provide a custom address for a specific host and port pair");
+ private static final CLOptionDescriptor D_LIMIT_RATE_OPT = new CLOptionDescriptor("limit-rate",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, LIMIT_RATE_OPT,
+ "Specify the maximum transfer rate you want curl to use");
+ private static final CLOptionDescriptor D_MAX_REDIRS = new CLOptionDescriptor("max-redirs",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, MAX_REDIRS_OPT, "Set maximum number of redirections");
+ private static final CLOptionDescriptor D_NOPROXY = new CLOptionDescriptor("noproxy",
+ CLOptionDescriptor.ARGUMENT_REQUIRED, NOPROXY_OPT,
+ "Comma-separated list of hosts which do not use a proxy, if one is specified. ");
+ private static final Pattern deleteLinePattern = Pattern.compile("\r|\n|\r\n");
private static final CLOptionDescriptor[] OPTIONS = new CLOptionDescriptor[] {
- D_COMPRESSED_OPT,
- D_HEADER_OPT,
- D_METHOD_OPT,
- D_DATA_OPT
+ D_COMPRESSED_OPT,D_HEADER_OPT, D_METHOD_OPT,D_DATA_OPT, D_DATA_ASCII_OPT, D_DATA_URLENCODE_OPT, D_DATA_RAW_OPT, D_DATA_BINARY_OPT,
+ D_FORM_OPT, D_FORM_STRING_OPT, D_USER_AGENT_OPT, D_CONNECT_TIMEOUT_OPT, D_COOKIE_OPT, D_USER_OPT,
+ D_BASIC_OPT, D_DIGEST_OPT, D_CACERT_OPT, D_CAPATH_OPT, D_CERT_OPT, D_CERT_STATUS_OPT, D_CERT_TYPE_OPT,
+ D_CIPHERS_OPT, D_KEY_OPT, D_KEY_TYPE_OPT, D_GET_OPT, D_DNS_SERVERS_OPT, D_NO_KEEPALIVE_OPT, D_REFERER_OPT,
+ D_LOCATION_OPT, D_INCLUDE_OPT, D_INSECURE_OPT, D_HEAD_OPT, D_PROXY_OPT, D_PROXY_USER_OPT, D_PROXY_NTLM_OPT,
+ D_PROXY_NEGOTIATE_OPT, D_KEEPALIVETILE_OPT, D_MAX_TIME_OPT, D_OUTPUT_OPT, D_CREATE_DIRS_OPT, D_RAW_OPT,
+ D_INTERFACE_OPT, D_DNS_RESOLVER_OPT, D_LIMIT_RATE_OPT, D_MAX_REDIRS ,D_NOPROXY
};
public BasicCurlParser() {
super();
}
-
public Request parse(String commandLine) {
String[] args = translateCommandline(commandLine);
CLArgsParser parser = new CLArgsParser(args, OPTIONS);
String error = parser.getErrorString();
- if(error == null) {
+ boolean isPostToGet = false;
+ if (error == null) {
List<CLOption> clOptions = parser.getArguments();
Request request = new Request();
for (CLOption option : clOptions) {
if (option.getDescriptor().getId() == CLOption.TEXT_ARGUMENT) {
// Curl or URL
- if(!"CURL".equalsIgnoreCase(option.getArgument())) {
+ if (!"CURL".equalsIgnoreCase(option.getArgument())) {
request.setUrl(option.getArgument());
- continue;
}
} else if (option.getDescriptor().getId() == COMPRESSED_OPT) {
request.setCompressed(true);
@@ -169,20 +676,103 @@ public class BasicCurlParser {
String nameAndValue = option.getArgument(0);
int indexOfSemicolon = nameAndValue.indexOf(':');
String name = nameAndValue.substring(0, indexOfSemicolon).trim();
- String value = nameAndValue.substring(indexOfSemicolon+1).trim();
+ String value = nameAndValue.substring(indexOfSemicolon + 1).trim();
request.addHeader(name, value);
} else if (option.getDescriptor().getId() == METHOD_OPT) {
String value = option.getArgument(0);
request.setMethod(value);
- } else if (option.getDescriptor().getId() == DATA_OPT) {
+ } else if (DATAS_OPT.contains(option.getDescriptor().getId())) {
String value = option.getArgument(0);
+ String dataOptionName = option.getDescriptor().getName();
+ value = getPostDataByDifferentOption(value.trim(), dataOptionName);
request.setMethod("POST");
request.setPostData(value);
+ } else if (FORMS_OPT.contains(option.getDescriptor().getId())) {
+ String nameAndValue = option.getArgument(0);
+ int indexOfEqual = nameAndValue.indexOf('=');
+ String key = nameAndValue.substring(0, indexOfEqual).trim();
+ String value = nameAndValue.substring(indexOfEqual + 1).trim();
+ if ("form-string".equals(option.getDescriptor().getName())) {
+ request.addFormStringData(key, value);
+ } else {
+ request.addFormData(key, value);
+ }
+ request.setMethod("POST");
+ } else if (option.getDescriptor().getId() == USER_AGENT_OPT) {
+ request.addHeader("User-Agent", option.getArgument(0));
+ } else if (option.getDescriptor().getId() == REFERER_OPT) {
+ request.addHeader("Referer", option.getArgument(0));
+ } else if (option.getDescriptor().getId() == CONNECT_TIMEOUT_OPT) {
+ String value = option.getArgument(0);
+ request.setConnectTimeout(Double.valueOf(value) * 1000);
+ } else if (option.getDescriptor().getId() == COOKIE_OPT) {
+ String value = option.getArgument(0);
+ if (isValidCookie(value)) {
+ request.setCookies(value);
+ } else {
+ request.setFilepathCookie(value);
+ }
+ } else if (option.getDescriptor().getId() == USER_OPT) {
+ String value = option.getArgument(0);
+ setAuthUserPasswd(value, request.getUrl(), request.getAuthorization());
+ } else if (AUTH_OPT.contains(option.getDescriptor().getId())) {
+ String authOption = option.getDescriptor().getName();
+ setAuthMechanism(authOption, request.getAuthorization());
+ } else if (SSL_OPT.contains(option.getDescriptor().getId())) {
+ request.setCacert(option.getDescriptor().getName());
+ } else if (option.getDescriptor().getId() == GET_OPT) {
+ isPostToGet = true;
+ } else if (option.getDescriptor().getId() == DNS_OPT) {
+ String value = option.getArgument(0);
+ String[] dnsServer = value.split(",");
+ for (String s : dnsServer) {
+ request.addDnsServers(s);
+ }
+ } else if (option.getDescriptor().getId() == NO_KEEPALIVE_OPT) {
+ request.setKeepAlive(false);
+ } else if (option.getDescriptor().getId() == PROXY_OPT) {
+ String value = option.getArgument(0);
+ setProxyServer(request, value);
+ } else if (option.getDescriptor().getId() == PROXY_USER_OPT) {
+ String value = option.getArgument(0);
+ setProxyServerUserInfo(request, value);
+ } else if (option.getDescriptor().getId() == MAX_TIME_OPT) {
+ String value = option.getArgument(0);
+ request.setMaxTime(Double.valueOf(value) * 1000);
+ } else if (option.getDescriptor().getId() == HEAD_OPT) {
+ request.setMethod("HEAD");
+ } else if (option.getDescriptor().getId() == INTERFACE_OPT) {
+ String value = option.getArgument(0);
+ request.setInterfaceName(value);
+ } else if (option.getDescriptor().getId() == DNS_RESOLVER_OPT) {
+ String value = option.getArgument(0);
+ request.setDnsResolver(value);
+ } else if (option.getDescriptor().getId() == LIMIT_RATE_OPT) {
+ String value = option.getArgument(0);
+ request.setLimitRate(value);
+ } else if (option.getDescriptor().getId() == NOPROXY_OPT) {
+ String value = option.getArgument(0);
+ request.setNoproxy(value);
+ } else if (IGNORE_OPTIONS_OPT.contains(option.getDescriptor().getId())) {
+ request.addOptionsIgnored(option.getDescriptor().getName());
+ } else if (NOSUPPORT_OPTIONS_OPT.contains(option.getDescriptor().getId())) {
+ request.addOptionsNoSupport(option.getDescriptor().getName());
+ } else if (PROPERTIES_OPT.contains(option.getDescriptor().getId())) {
+ request.addOptionsInProperties(
+ "--" + option.getDescriptor().getName() + " is in 'httpsampler.max_redirects(1062 line)'");
}
}
+ if (isPostToGet) {
+ String url = request.getUrl();
+ url += "?" + request.getPostData();
+ request.setUrl(url);
+ request.setPostData(null);
+ request.setMethod("GET");
+ }
return request;
} else {
- throw new IllegalArgumentException("Unexpected format for command line:"+commandLine+", error:"+error);
+ throw new IllegalArgumentException(
+ "Unexpected format for command line:" + commandLine + ", error:" + error);
}
}
@@ -252,4 +842,233 @@ public class BasicCurlParser {
}
return result.toArray(new String[result.size()]);
}
+ /**
+ *
+ * Set the username , password and baseurl of authorization
+ *
+ * @param authentication the username and password of authorization
+ * @param url the baseurl of authorization
+ * @param authorization the object of authorization
+ */
+ public void setAuthUserPasswd(String authentication, String url, Authorization authorization) {
+ String[] authorizationParameters = authentication.split(":", 2);
+ authorization.setUser(authorizationParameters[0].trim());
+ authorization.setPass(authorizationParameters[1].trim());
+ authorization.setURL(url);
+ }
+
+ /**
+ *
+ * Set the mechanism of authorization
+ *
+ * @param mechanism the mechanism of authorization
+ * @param authorization the object of authorization
+ */
+ private void setAuthMechanism(String mechanism, Authorization authorization) {
+ switch (mechanism.toLowerCase()) {
+ case "basic":
+ authorization.setMechanism(Mechanism.BASIC);
+ break;
+ case "digest":
+ authorization.setMechanism(Mechanism.DIGEST);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ *
+ * Set the parameters of proxy server in http request advanced
+ *
+ * @param request http request
+ * @param proxyServerParameters the parameters of proxy server
+ *
+ */
+ private void setProxyServer(Request request, String proxyServerParameters) {
+ if (!proxyServerParameters.contains("://")) {
+ proxyServerParameters = "http://" + proxyServerParameters;
+ }
+ URI uriProxy = null;
+ try {
+ uriProxy = new URI(proxyServerParameters);
+ request.setProxyServer("scheme", uriProxy.getScheme());
+ Optional<String> userInfoOptional = Optional.ofNullable(uriProxy.getUserInfo());
+ if (userInfoOptional.isPresent()) {
+ setProxyServerUserInfo(request, userInfoOptional.get());
+ }
+ Optional<String> hostOptional = Optional.ofNullable(uriProxy.getHost());
+ if (hostOptional.isPresent()) {
+ request.setProxyServer("servername", hostOptional.get());
+ }
+ if (uriProxy.getPort() != -1) {
+ request.setProxyServer("port", String.valueOf(uriProxy.getPort()));
+ } else {
+ request.setProxyServer("port", "1080");
+ }
+ } catch (URISyntaxException e) {
+ LOGGER.error("string '{}' cannot be converted to a URL", proxyServerParameters);
+ throw new IllegalArgumentException(proxyServerParameters + " cannot be converted to a URL");
+ }
+ }
+
+ /**
+ * Set the username and password of proxy server
+ *
+ * @param request http request
+ * @param authentication the username and password of proxy server
+ */
+ private void setProxyServerUserInfo(Request request, String authentication) {
+ if (authentication.contains(":")) {
+ String[] userInfo = authentication.split(":", 2);
+ request.setProxyServer("username", userInfo[0]);
+ request.setProxyServer("password", userInfo[1]);
+ }
+ }
+
+ /**
+ * Get post data by different type of data option
+ *
+ * @param postdata the post data
+ * @param dataOptionName the different option of "--data"
+ * @return the post data
+ */
+ private String getPostDataByDifferentOption(String postdata, String dataOptionName) {
+ if ("data-urlencode".equals(dataOptionName)) {
+ postdata = encodePostdata(postdata);
+ } else {
+ if (postdata.charAt(0) == '@' && !"data-raw".equals(dataOptionName)) {
+ postdata = postdata.substring(1, postdata.length());
+ postdata = readFromFile(postdata);
+ if (!"data-binary".equals(dataOptionName)) {
+ postdata = deleteLineBreak(postdata);
+ }
+ }
+ }
+ return postdata;
+ }
+
+ /**
+ * Encode the post data
+ *
+ * @param postdata the post data
+ * @return the result of encoding
+ *
+ */
+ private String encodePostdata(String postdata) {
+ if (postdata.contains("@")) {
+ String contentFile = null;
+ String[] arr = postdata.split("@", 2);
+ String dataToEncode = readFromFile(arr[1]);
+ try {
+ contentFile = URLEncoder.encode(dataToEncode, StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ LOGGER.error("string '{}' cannot be encoded", dataToEncode);// NOSONAR
+ }
+ if (!arr[0].isEmpty()) {
+ contentFile = arr[0] + "=" + contentFile;
+ }
+ return contentFile;
+ } else {
+ if (!postdata.contains("=")) {
+ try {
+ return URLEncoder.encode(postdata, StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ LOGGER.error("string '{}' cannot be encoded", postdata);
+ throw new IllegalArgumentException(postdata + " cannot be encoded");
+ }
+ } else {
+ int index = postdata.indexOf('=');
+ try {
+ return postdata.substring(0, index + 1) + URLEncoder
+ .encode(postdata.substring(index + 1, postdata.length()), StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ LOGGER.error("string '{}' cannot be encoded", postdata.substring(index + 1, postdata.length()));
+ throw new IllegalArgumentException(
+ postdata.substring(index + 1, postdata.length()) + " cannot be encoded");
+ }
+ }
+ }
+ }
+
+ /**
+ * Read the postdata from file
+ *
+ * @param filePath
+ * @return the content of file
+ */
+ private static String readFromFile(String filePath) {
+ String content = "";
+ File file = new File(filePath.trim());
+ if (file.isFile() && file.exists()) {
+ try {
+ content = FileUtils.readFileToString(file, StandardCharsets.UTF_8.name());
+ } catch (IOException e) {
+ LOGGER.error("Failed to read from File {}", filePath);
+ throw new IllegalArgumentException("Failed to read from File " + filePath);
+ }
+ } else {
+ throw new IllegalArgumentException(filePath + " is a directory or does not exist");
+ }
+ return content;
+ }
+
+ /**
+ * Delete line break
+ *
+ * @param postdata the post data
+ * @return the string without break line
+ */
+ private static String deleteLineBreak(String postdata) {
+ Matcher m = deleteLinePattern.matcher(postdata);
+ return m.replaceAll("");
+ }
+
+ /**
+ * Verify if the string is cookie or filename
+ * @param str
+ * @return Whether the format of the string is cookie
+ */
+ public static boolean isValidCookie(String str) {
+ for (String r : str.split(";")) {
+ if (!r.contains("=")) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Convert string to cookie
+ *
+ * @param cookieStr
+ * @param url
+ * @return list of cookies
+ */
+ public static List<Cookie> stringToCookie(String cookieStr, String url) {
+ List<Cookie> cookies = new ArrayList<>();
+ final StringTokenizer tok = new StringTokenizer(cookieStr, "; ", true);
+ while (tok.hasMoreTokens()) {
+ String nextCookie = tok.nextToken();
+ if (nextCookie.contains("=")) {
+ String[] cookieParameters = nextCookie.split("=", 2);
+ if (!DYNAMIC_COOKIES.contains(cookieParameters[0])) {
+ Cookie newCookie = new Cookie();
+ newCookie.setName(cookieParameters[0]);
+ newCookie.setValue(cookieParameters[1]);
+ URL newUrl;
+ try {
+ newUrl = new URL(url.trim());
+ newCookie.setDomain(newUrl.getHost());
+ newCookie.setPath(newUrl.getPath());
+ cookies.add(newCookie);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(
+ "unqualified url " + url.trim() + ", unable to create cookies.");
+ }
+ }
+ }
+ }
+ return cookies;
+ }
}
diff --git a/src/protocol/http/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java b/src/protocol/http/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java
index abc18af..220a297 100644
--- a/src/protocol/http/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java
+++ b/src/protocol/http/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java
@@ -15,26 +15,32 @@
* limitations under the License.
*
*/
-
package org.apache.jmeter.protocol.http.gui.action;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
-import java.awt.GridLayout;
+import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.activation.MimetypesFileTypeMap;
import javax.swing.JButton;
+import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
@@ -43,7 +49,9 @@ import javax.swing.MenuElement;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;
+import org.apache.commons.io.FileUtils;
import org.apache.jmeter.config.Arguments;
+import org.apache.jmeter.config.KeystoreConfig;
import org.apache.jmeter.control.Controller;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.control.ReplaceableController;
@@ -57,18 +65,30 @@ import org.apache.jmeter.gui.plugin.MenuCreator;
import org.apache.jmeter.gui.tree.JMeterTreeModel;
import org.apache.jmeter.gui.tree.JMeterTreeNode;
import org.apache.jmeter.gui.util.EscapeDialog;
+import org.apache.jmeter.gui.util.FilePanel;
import org.apache.jmeter.gui.util.JSyntaxTextArea;
import org.apache.jmeter.gui.util.JTextScrollPane;
+import org.apache.jmeter.protocol.http.control.AuthManager;
+import org.apache.jmeter.protocol.http.control.Authorization;
+import org.apache.jmeter.protocol.http.control.Cookie;
+import org.apache.jmeter.protocol.http.control.CookieManager;
+import org.apache.jmeter.protocol.http.control.DNSCacheManager;
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager;
+import org.apache.jmeter.protocol.http.control.StaticHost;
import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui;
import org.apache.jmeter.protocol.http.curl.BasicCurlParser;
import org.apache.jmeter.protocol.http.curl.BasicCurlParser.Request;
+import org.apache.jmeter.protocol.http.gui.AuthPanel;
+import org.apache.jmeter.protocol.http.gui.CookiePanel;
+import org.apache.jmeter.protocol.http.gui.DNSCachePanel;
import org.apache.jmeter.protocol.http.gui.HeaderPanel;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
+import org.apache.jmeter.protocol.http.util.HTTPFileArg;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.services.FileServer;
+import org.apache.jmeter.testbeans.gui.TestBeanGUI;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.threads.AbstractThreadGroup;
@@ -82,27 +102,26 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Opens a popup where user can enter a cURL command line and create a test plan from it
+ * Opens a popup where user can enter a cURL command line and create a test plan
+ * from it
+ *
* @since 5.1
*/
public class ParseCurlCommandAction extends AbstractAction implements MenuCreator, ActionListener { // NOSONAR
-
private static final Logger LOGGER = LoggerFactory.getLogger(ParseCurlCommandAction.class);
private static final String ACCEPT_ENCODING = "Accept-Encoding";
private static final Set<String> commands = new HashSet<>();
- public static final String IMPORT_CURL = "import_curl";
+ public static final String IMPORT_CURL = "import_curl";
private static final String CREATE_REQUEST = "CREATE_REQUEST";
-
+ private static final String TYPE_FORM = ";type=";
+ /** A panel allowing results to be saved. */
+ private FilePanel filePanel = null;
static {
commands.add(IMPORT_CURL);
}
-
private JSyntaxTextArea cURLCommandTA;
private JLabel statusText;
-
- /**
- *
- */
+ private JCheckBox uploadCookiesCheckBox;
public ParseCurlCommandAction() {
super();
}
@@ -114,27 +133,31 @@ public class ParseCurlCommandAction extends AbstractAction implements MenuCreato
/**
* Show popup where user can import cURL command
+ *
* @param event {@link ActionEvent}
*/
private final void showInputDialog(ActionEvent event) {
- EscapeDialog messageDialog = new EscapeDialog(getParentFrame(event),
- JMeterUtils.getResString("curl_import"), false); //$NON-NLS-1$
+ EscapeDialog messageDialog = new EscapeDialog(getParentFrame(event), JMeterUtils.getResString("curl_import"), //$NON-NLS-1$
+ false);
Container contentPane = messageDialog.getContentPane();
contentPane.setLayout(new BorderLayout());
- statusText = new JLabel("", JLabel.CENTER);
+ statusText = new JLabel("",JLabel.CENTER);
statusText.setForeground(Color.RED);
contentPane.add(statusText, BorderLayout.NORTH);
-
- cURLCommandTA = JSyntaxTextArea.getInstance(10, 80, false);
+ cURLCommandTA = JSyntaxTextArea.getInstance(20, 80, false);
cURLCommandTA.setCaretPosition(0);
contentPane.add(JTextScrollPane.getInstance(cURLCommandTA), BorderLayout.CENTER);
-
- JPanel buttonPanel = new JPanel(new GridLayout(1, 1));
+ JPanel optionPanel = new JPanel(new BorderLayout(3, 1));
+ filePanel = new FilePanel(JMeterUtils.getResString("curl_import_from_file")); // $NON-NLS-1$
+ optionPanel.add(filePanel,BorderLayout.CENTER);
+ uploadCookiesCheckBox = new JCheckBox(JMeterUtils.getResString("curl_add_cookie_header_to_cookiemanager"), false);
+ optionPanel.add(uploadCookiesCheckBox,BorderLayout.NORTH);
JButton button = new JButton(JMeterUtils.getResString("curl_create_request"));
button.setActionCommand(CREATE_REQUEST);
button.addActionListener(this);
- buttonPanel.add(button);
- contentPane.add(buttonPanel, BorderLayout.SOUTH);
+ button.setPreferredSize(new Dimension(50, 50));
+ optionPanel.add(button,BorderLayout.SOUTH);
+ contentPane.add(optionPanel, BorderLayout.SOUTH);
messageDialog.pack();
ComponentUtil.centerComponentInComponent(GuiPackage.getInstance().getMainFrame(), messageDialog);
SwingUtilities.invokeLater(() -> messageDialog.setVisible(true));
@@ -143,25 +166,34 @@ public class ParseCurlCommandAction extends AbstractAction implements MenuCreato
/**
* Finds the first enabled node of a given type in the tree.
*
- * @param type class of the node to be found
+ * @param type class of the node to be found
* @return the first node of the given type in the test component tree, or
- * <code>null</code> if none was found.
+ * <code>null</code> if none was found.
*/
private JMeterTreeNode findFirstNodeOfType(Class<?> type) {
JMeterTreeModel treeModel = GuiPackage.getInstance().getTreeModel();
- return treeModel.getNodesOfType(type).stream()
- .filter(JMeterTreeNode::isEnabled)
- .findFirst()
- .orElse(null);
+ return treeModel.getNodesOfType(type).stream().filter(JMeterTreeNode::isEnabled).findFirst().orElse(null);
+ }
+
+ private DNSCacheManager findNodeOfTypeDnsCacheManagerByType(boolean isCustom) {
+ JMeterTreeModel treeModel = GuiPackage.getInstance().getTreeModel();
+ DNSCacheManager dnsCacheManager=new DNSCacheManager();
+ List<JMeterTreeNode> res = treeModel.getNodesOfType(DNSCacheManager.class);
+ for (JMeterTreeNode jm : res) {
+ dnsCacheManager = (DNSCacheManager) jm.getTestElement();
+ if (dnsCacheManager.isCustomResolver()==isCustom) {
+ return dnsCacheManager;
+ }
+ }
+ return null;
}
- private void createTestPlan(ActionEvent e, Request request) throws MalformedURLException, IllegalUserActionException {
+ private void createTestPlan(ActionEvent e, Request request, String statusText)
+ throws MalformedURLException, IllegalUserActionException {
ActionRouter.getInstance().doActionNow(new ActionEvent(e.getSource(), e.getID(), ActionNames.CLOSE));
GuiPackage guiPackage = GuiPackage.getInstance();
-
guiPackage.clearTestPlan();
FileServer.getFileServer().setScriptName(null);
-
ThreadGroup threadGroup = new ThreadGroup();
threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName());
threadGroup.setProperty(TestElement.NAME, "Thread Group");
@@ -170,76 +202,126 @@ public class ParseCurlCommandAction extends AbstractAction implements MenuCreato
threadGroup.setScheduler(true);
threadGroup.setDuration(3600);
threadGroup.setDelay(5);
-
LoopController loopCtrl = new LoopController();
loopCtrl.setLoops(-1);
loopCtrl.setContinueForever(true);
threadGroup.setSamplerController(loopCtrl);
-
TestPlan testPlan = new TestPlan();
testPlan.setProperty(TestElement.NAME, "Test Plan");
testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName());
-
HashTree tree = new HashTree();
HashTree testPlanHT = tree.add(testPlan);
HashTree threadGroupHT = testPlanHT.add(threadGroup);
-
- createHttpRequest(request, threadGroupHT);
-
+ createHttpRequest(request, threadGroupHT,statusText);
+ if (!request.getAuthorization().getUser().isEmpty()) {
+ AuthManager authManager = new AuthManager();
+ createAuthManager(request, authManager);
+ threadGroupHT.add(authManager);
+ }
+ if (!request.getDnsServers().isEmpty()) {
+ DNSCacheManager dnsCacheManager = new DNSCacheManager();
+ createDnsServer(request, dnsCacheManager);
+ threadGroupHT.add(dnsCacheManager);
+ }
+ if (request.getDnsResolver()!=null) {
+ DNSCacheManager dnsCacheManager = new DNSCacheManager();
+ createDnsResolver(request, dnsCacheManager);
+ threadGroupHT.add(dnsCacheManager);
+ }
+ CookieManager cookieManager = new CookieManager();
+ createCookieManager(cookieManager, request);
+ threadGroupHT.add(cookieManager);
ResultCollector resultCollector = new ResultCollector();
resultCollector.setProperty(TestElement.NAME, "View Results Tree");
resultCollector.setProperty(TestElement.GUI_CLASS, ViewResultsFullVisualizer.class.getName());
tree.add(tree.getArray()[0], resultCollector);
-
final HashTree newTree = guiPackage.addSubTree(tree);
guiPackage.updateCurrentGui();
- guiPackage.getMainFrame().getTree().setSelectionPath(
- new TreePath(((JMeterTreeNode) newTree.getArray()[0]).getPath()));
+ guiPackage.getMainFrame().getTree()
+ .setSelectionPath(new TreePath(((JMeterTreeNode) newTree.getArray()[0]).getPath()));
final HashTree subTree = guiPackage.getCurrentSubTree();
- // Send different event wether we are merging a test plan into another test plan,
+ // Send different event wether we are merging a test plan into another test
+ // plan,
// or loading a testplan from scratch
- ActionEvent actionEvent =
- new ActionEvent(subTree.get(subTree.getArray()[subTree.size() - 1]), e.getID(), ActionNames.SUB_TREE_LOADED);
+ ActionEvent actionEvent = new ActionEvent(subTree.get(subTree.getArray()[subTree.size() - 1]), e.getID(),
+ ActionNames.SUB_TREE_LOADED);
ActionRouter.getInstance().actionPerformed(actionEvent);
ActionRouter.getInstance().doActionNow(new ActionEvent(e.getSource(), e.getID(), ActionNames.EXPAND_ALL));
}
- private HTTPSamplerProxy createHttpRequest(Request request, HashTree parentHT) throws MalformedURLException {
- HTTPSamplerProxy httpSampler = createSampler(request);
-
+ private HTTPSamplerProxy createHttpRequest(Request request, HashTree parentHT, String commentText) throws MalformedURLException {
+ HTTPSamplerProxy httpSampler = createSampler(request,commentText);
HashTree samplerHT = parentHT.add(httpSampler);
samplerHT.add(httpSampler.getHeaderManager());
+ if (request.getCaCert().equals("cert")) {
+ samplerHT.add(httpSampler.getKeystoreConfig());
+ }
return httpSampler;
}
/**
- * @param request {@link Request}
+ * @param request {@link Request}
+ * @param statusText
* @return {@link HTTPSamplerProxy}
* @throws MalformedURLException
*/
- private HTTPSamplerProxy createSampler(Request request) throws MalformedURLException {
- HTTPSamplerProxy httpSampler = (HTTPSamplerProxy) HTTPSamplerFactory.newInstance(HTTPSamplerFactory.DEFAULT_CLASSNAME);
+ private HTTPSamplerProxy createSampler(Request request, String commentText) throws MalformedURLException {
+ HTTPSamplerProxy httpSampler = (HTTPSamplerProxy) HTTPSamplerFactory
+ .newInstance(HTTPSamplerFactory.DEFAULT_CLASSNAME);
httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
httpSampler.setProperty(TestElement.NAME, "HTTP Request");
- httpSampler.setProperty(TestElement.COMMENTS, "Created from cURL on "+LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
+ if (!commentText.isEmpty()) {
+ httpSampler.setProperty(TestElement.COMMENTS,commentText); // NOSONAR
+ } else {
+ httpSampler.setProperty(TestElement.COMMENTS,
+ "Created from cURL on " + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
+ } // NOSONAR
httpSampler.setProtocol(new URL(request.getUrl()).getProtocol());
- httpSampler.setPath(request.getUrl());
- httpSampler.setUseKeepAlive(true);
+ httpSampler.setPath(new URL(request.getUrl()).getPath());
+ httpSampler.setDomain(new URL(request.getUrl()).getHost());
+ httpSampler.setUseKeepAlive(request.isKeepAlive());
httpSampler.setFollowRedirects(true);
httpSampler.setMethod(request.getMethod());
- if (!"GET".equals(request.getMethod())) {
+ HeaderManager headerManager = createHeaderManager(request);
+ httpSampler.addTestElement(headerManager);
+ configureTimeout(request, httpSampler);
+ createProxyServer(request, httpSampler);
+ if (request.getInterfaceName() != null) {
+ httpSampler.setIpSourceType(1);
+ httpSampler.setIpSource(request.getInterfaceName());
+ }
+ if (!"GET".equals(request.getMethod()) && request.getPostData() != null) {
Arguments arguments = new Arguments();
httpSampler.setArguments(arguments);
httpSampler.addNonEncodedArgument("", request.getPostData(), "");
}
-
- HeaderManager headerManager = createHeaderManager(request);
- httpSampler.addTestElement(headerManager);
-
+ if (!request.getFormData().isEmpty() || !request.getFormStringData().isEmpty()) {
+ setFormData(request, httpSampler);
+ httpSampler.setDoMultipart(true);
+ }
+ if (request.getCaCert().equals("cert")) {
+ KeystoreConfig keystoreConfig = createKeystoreConfiguration();
+ httpSampler.addTestElement(keystoreConfig);
+ }
return httpSampler;
}
+ private void configureTimeout(Request request, HTTPSamplerProxy httpSampler) {
+ double connectTimeout = request.getConnectTimeout();
+ double maxTime = request.getMaxTime();
+ if (connectTimeout >= 0) {
+ httpSampler.setConnectTimeout(String.valueOf((int) request.getConnectTimeout()));
+ if (maxTime >= 0) {
+ maxTime = maxTime - connectTimeout;
+ }
+ }
+ if (maxTime >= 0) {
+ httpSampler.setResponseTimeout(String.valueOf((int) maxTime));
+ }
+ }
+
/**
+ *
* @param request {@link Request}
* @return {@link HeaderManager} element
*/
@@ -247,108 +329,519 @@ public class ParseCurlCommandAction extends AbstractAction implements MenuCreato
HeaderManager headerManager = new HeaderManager();
headerManager.setProperty(TestElement.GUI_CLASS, HeaderPanel.class.getName());
headerManager.setProperty(TestElement.NAME, "HTTP HeaderManager");
- headerManager.setProperty(TestElement.COMMENTS, "Created from cURL on "+LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
+ headerManager.setProperty(TestElement.COMMENTS,
+ "Created from cURL on " + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
Map<String, String> map = request.getHeaders();
-
boolean hasAcceptEncoding = false;
for (Map.Entry<String, String> header : map.entrySet()) {
String key = header.getKey();
hasAcceptEncoding = hasAcceptEncoding || key.equalsIgnoreCase(ACCEPT_ENCODING);
headerManager.getHeaders().addItem(new Header(key, header.getValue()));
}
- if(!hasAcceptEncoding && request.isCompressed()) {
+ if (!hasAcceptEncoding && request.isCompressed()) {
headerManager.getHeaders().addItem(new Header(ACCEPT_ENCODING, "gzip, deflate"));
}
return headerManager;
}
- @Override
- public Set<String> getActionNames() {
- return commands;
+ /**
+ * Create Cookie Manager
+ *
+ * @param request {@link Request}
+ * @return{@link CookieManager} element
+ */
+ private void createCookieManager(CookieManager cookieManager,Request request) {
+ cookieManager.setProperty(TestElement.GUI_CLASS, CookiePanel.class.getName());
+ cookieManager.setProperty(TestElement.NAME, "HTTP CookieManager");
+ cookieManager.setProperty(TestElement.COMMENTS,
+ "Created from cURL on " + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
+ if (!request.getCookies(request.getUrl()).isEmpty()) {
+ for (Cookie c : request.getCookies(request.getUrl())) {
+ cookieManager.getCookies().addItem(c);
+ }
+ }
+ if (!request.getCookieInHeaders(request.getUrl()).isEmpty()&&uploadCookiesCheckBox.isSelected()) {
+ for (Cookie c : request.getCookieInHeaders(request.getUrl())) {
+ cookieManager.getCookies().addItem(c);
+ }
+ }
+ if (!request.getFilepathCookie().isEmpty()) {
+ String pathfileCookie=request.getFilepathCookie();
+ File file = new File(pathfileCookie);
+ if (file.isFile() && file.exists()) {
+ try {
+ cookieManager.addFile(pathfileCookie);
+ } catch (IOException e) {
+ LOGGER.error("Failed to read from File {}", pathfileCookie);
+ throw new IllegalArgumentException("Failed to read from File " + pathfileCookie);
+ }
+ } else {
+ LOGGER.error("File {} doesn't exist", pathfileCookie);
+ throw new IllegalArgumentException("File " + pathfileCookie + " doesn't exist");
+ }
+ }
}
- @Override
- public JMenuItem[] getMenuItemsAtLocation(MENU_LOCATION location) {
- if(location == MENU_LOCATION.TOOLS) {
- JMenuItem menuItemIC = new JMenuItem(
- JMeterUtils.getResString("curl_import_menu"), KeyEvent.VK_UNDEFINED);
- menuItemIC.setName(IMPORT_CURL);
- menuItemIC.setActionCommand(IMPORT_CURL);
- menuItemIC.setAccelerator(null);
- menuItemIC.addActionListener(ActionRouter.getInstance());
- return new JMenuItem[]{menuItemIC};
- }
- return new JMenuItem[0];
+ /**
+ * Create Keystore Configuration
+ *
+ * @param request {@link Request}
+ * @return{@link KeystoreConfig} element
+ */
+ private KeystoreConfig createKeystoreConfiguration() {
+ KeystoreConfig keystoreConfig = new KeystoreConfig();
+ keystoreConfig.setProperty(TestElement.GUI_CLASS, TestBeanGUI.class.getName());
+ keystoreConfig.setProperty(TestElement.NAME, "Keystore Configuration");
+ keystoreConfig.setProperty(TestElement.COMMENTS,
+ "Created from cURL on " + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
+ return keystoreConfig;
}
- @Override
- public JMenu[] getTopLevelMenus() {
- return new JMenu[0];
+ /**
+ * Create Authorization manager
+ *
+ * @param request {@link Request}
+ * @return {@link AuthManager} element
+ */
+ private void createAuthManager(Request request, AuthManager authManager) {
+ Authorization auth = request.getAuthorization();
+ authManager.setProperty(TestElement.GUI_CLASS, AuthPanel.class.getName());
+ authManager.setProperty(TestElement.NAME, "HTTP AuthorizationManager");
+ authManager.setProperty(TestElement.COMMENTS,
+ "Created from cURL on " + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
+ authManager.getAuthObjects().addItem(auth);
}
- @Override
- public boolean localeChanged(MenuElement menu) {
+ /**
+ * Whether to update Authorization Manager in http request
+ *
+ * @param request {@link Request}
+ * @param authManager {@link AuthManager} element
+ * @return whether to update Authorization Manager in http request
+ */
+ private boolean canAddAuthManagerInHttpRequest(Request request, AuthManager authManager) {
+ Authorization auth = request.getAuthorization();
+ for (int i = 0; i < authManager.getAuthObjects().size(); i++) {
+ if (!authManager.getAuthObjectAt(i).getUser().equals(auth.getUser())
+ || !authManager.getAuthObjectAt(i).getPass().equals(auth.getPass())
+ || !authManager.getAuthObjectAt(i).getMechanism().equals(auth.getMechanism())) {
+ return true;
+ }
+ }
return false;
}
+ /**
+ * Whether to update Authorization Manager in Thread Group
+ *
+ * @param request {@link Request}
+ * @param authManager {@link AuthManager} element
+ * @return whether to update Authorization Manager in Thread Group
+ */
+ private boolean canUpdateAuthManagerInThreadGroup(Request request, AuthManager authManager) {
+ Authorization auth = request.getAuthorization();
+ for (int i = 0; i < authManager.getAuthObjects().size(); i++) {
+ if (auth.getURL().equals(authManager.getAuthObjectAt(i).getURL())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Create DnsCacheManager
+ *
+ * @param request {@link Request}
+ * @return{@link DnsCacheManager} element
+ */
+ private void createDnsServer(Request request, DNSCacheManager dnsCacheManager) {
+ Set<String> dnsServers = request.getDnsServers();
+ dnsCacheManager.setProperty(TestElement.GUI_CLASS, DNSCachePanel.class.getName());
+ dnsCacheManager.setProperty(TestElement.NAME, "DNS Cache Manager");
+ dnsCacheManager.setProperty(TestElement.COMMENTS,
+ "Created from cURL on " + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
+ dnsCacheManager.getServers().clear();
+ for (String dnsServer : dnsServers) {
+ dnsCacheManager.addServer(dnsServer);
+ }
+ }
+
+ private boolean canAddDnsServerInHttpRequest(Request request, DNSCacheManager dnsCacheManager) {
+ Set<String> currentDnsServers =new HashSet<>();
+ Set<String> newDnsServers = request.getDnsServers();
+ for (int i = 0; i < dnsCacheManager.getServers().size(); i++) {
+ currentDnsServers.add(dnsCacheManager.getServers().get(i).getStringValue());
+ }
+ return !(newDnsServers.size() == currentDnsServers.size() && newDnsServers.containsAll(currentDnsServers));
+ }
+ /**
+ * Create DnsCacheManager
+ *
+ * @param request {@link Request}
+ * @return{@link DnsCacheManager} element
+ */
+ private void createDnsResolver(Request request, DNSCacheManager dnsCacheManager) {
+ dnsCacheManager.setProperty(TestElement.GUI_CLASS, DNSCachePanel.class.getName());
+ dnsCacheManager.setProperty(TestElement.NAME, "DNS Cache Manager");
+ dnsCacheManager.setCustomResolver(true);
+ dnsCacheManager.getHosts().clear();
+ String[]resolveParameters=request.getDnsResolver().split(":");
+ String port=resolveParameters[1];
+ if(!port.equals("443")&&!port.equals("80")&&!port.equals("*")) {
+ dnsCacheManager.setProperty(TestElement.COMMENTS,
+ "Custom DNS resolver doesn't support port "+port);
+ }
+ else {
+ dnsCacheManager.setProperty(TestElement.COMMENTS,
+ "Created from cURL on " + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
+ }
+ dnsCacheManager.addHost(resolveParameters[0], resolveParameters[2]);
+ }
+
+ private boolean canAddDnsResolverInHttpRequest(Request request, DNSCacheManager dnsCacheManager) {
+ if (dnsCacheManager.getHosts().size() != 1) {
+ return true;
+ } else {
+ String[] resolveParameters = request.getDnsResolver().split(":");
+ String host = resolveParameters[0];
+ String address = resolveParameters[2];
+ StaticHost statichost = (StaticHost) dnsCacheManager.getHosts().get(0).getObjectValue();
+ if (statichost.getAddress().equals(address) && statichost.getName().equals(host)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ /**
+ * Set parameters in http request
+ *
+ * @param request {@link Request}
+ * @param httpSampler
+ */
+ private void setFormData(Request request, HTTPSamplerProxy httpSampler) {
+ if (request.getPostData() != null) {
+ throw new IllegalArgumentException("--form and --data can't appear in the same command");
+ }
+ List<HTTPFileArg> httpFileArgs = new ArrayList<>();
+ for (Map.Entry<String, String> entry : request.getFormStringData().entrySet()) {
+ String formName = entry.getKey();
+ String formValue = entry.getValue();
+ httpSampler.addNonEncodedArgument(formName, formValue, "");
+ }
+ for (Map.Entry<String, String> entry : request.getFormData().entrySet()) {
+ String formName = entry.getKey();
+ String formValue = entry.getValue();
+ String contentType = "";
+ boolean isContainsFile = formValue.substring(0, 1).equals("@");
+ boolean isContainsContentType = formValue.toLowerCase().contains(TYPE_FORM);
+ if (isContainsFile) {
+ formValue = formValue.substring(1, formValue.length());
+ if (isContainsContentType) {
+ String[] formValueWithType = formValue.split(TYPE_FORM);
+ formValue = formValueWithType[0];
+ contentType = formValueWithType[1];
+ } else {
+ contentType = new MimetypesFileTypeMap().getContentType(formValue);
+ }
+ httpFileArgs.add(new HTTPFileArg(formValue, formName, contentType));
+ } else {
+ if (isContainsContentType) {
+ String[] formValueWithType = formValue.split(TYPE_FORM);
+ formValue = formValueWithType[0];
+ contentType = formValueWithType[1];
+ httpSampler.addNonEncodedArgument(formName, formValue, "", contentType);
+ } else {
+ httpSampler.addNonEncodedArgument(formName, formValue, "");
+ }
+ }
+ }
+ if (!httpFileArgs.isEmpty()) {
+ httpSampler.setHTTPFiles(httpFileArgs.toArray(new HTTPFileArg[httpFileArgs.size()]));
+ }
+ }
+ /**
+ *
+ * @param request {@link Request}
+ * @param httpSampler
+ */
+ private void createProxyServer(Request request, HTTPSamplerProxy httpSampler) {
+ Map<String, String> proxyServer = request.getProxyServer();
+ for (Map.Entry<String, String> proxyPara : proxyServer.entrySet()) {
+ String key = proxyPara.getKey();
+ switch (key) {
+ case "servername":
+ httpSampler.setProxyHost(proxyPara.getValue());
+ break;
+ case "port":
+ httpSampler.setProxyPortInt(proxyPara.getValue());
+ break;
+ case "scheme":
+ httpSampler.setProxyScheme(proxyPara.getValue());
+ break;
+ case "username":
+ httpSampler.setProxyUser(proxyPara.getValue());
+ break;
+ case "password":
+ httpSampler.setProxyPass(proxyPara.getValue());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
@Override
- public void localeChanged() {
- // NOOP
+ public JMenuItem[] getMenuItemsAtLocation(MENU_LOCATION location) {
+ if (location == MENU_LOCATION.TOOLS) {
+ JMenuItem menuItemIC = new JMenuItem(JMeterUtils.getResString("curl_import_menu"), KeyEvent.VK_UNDEFINED);
+ menuItemIC.setName(IMPORT_CURL);
+ menuItemIC.setActionCommand(IMPORT_CURL);
+ menuItemIC.setAccelerator(null);
+ menuItemIC.addActionListener(ActionRouter.getInstance());
+ return new JMenuItem[] { menuItemIC };
+ }
+ return new JMenuItem[0];
}
@Override
public void actionPerformed(ActionEvent e) {
statusText.setText("");
statusText.setForeground(Color.GREEN);
- if(e.getActionCommand().equals(CREATE_REQUEST)) {
- String curlCommand = cURLCommandTA.getText();
+ boolean isReadFromFile = false;
+ if (e.getActionCommand().equals(CREATE_REQUEST)) {
+ List<String> commandsList = null;
try {
- LOGGER.info("Transforming CURL command {}", curlCommand);
- BasicCurlParser basicCurlParser = new BasicCurlParser();
- BasicCurlParser.Request request = basicCurlParser.parse(curlCommand);
- LOGGER.info("Parsed CURL command {} into {}", curlCommand, request);
- GuiPackage guiPackage = GuiPackage.getInstance();
- guiPackage.updateCurrentNode();
- JMeterTreeNode treeNode = findFirstNodeOfType(AbstractThreadGroup.class);
- if(treeNode == null) {
- LOGGER.info("No AbstractThreadGroup found, potentially empty plan, creating a new plan");
- createTestPlan(e, request);
+ if (!filePanel.getFilename().trim().isEmpty() && cURLCommandTA.getText().trim().isEmpty()) {
+ commandsList = readFromFile(filePanel.getFilename().trim());
+ isReadFromFile = true;
+ } else if (filePanel.getFilename().trim().isEmpty() && !cURLCommandTA.getText().trim().isEmpty()) {
+ commandsList = readFromTextPanel(cURLCommandTA.getText().trim());
} else {
- JMeterTreeNode currentNode = guiPackage.getCurrentNode();
- Object userObject = currentNode.getUserObject();
- if (userObject instanceof Controller &&
- ! (userObject instanceof ReplaceableController)) {
- LOGGER.info("Newly created element will be placed under current selected node {}", currentNode.getName());
- addToTestPlan(currentNode, request);
- } else {
- LOGGER.info("Newly created element will be placed under first AbstractThreadGroup node {}", treeNode.getName());
- addToTestPlan(treeNode, request);
+ throw new IllegalArgumentException(
+ "Error creating tast plan ,Please select one between reading file and directly fill in the panel");
+ }
+ List<Request> requests = parseCommands(isReadFromFile, commandsList);
+ for (int i=0;i<requests.size();i++) {
+ BasicCurlParser.Request request = requests.get(i);
+ try {
+ String commentText = createCommentText(request);
+ GuiPackage guiPackage = GuiPackage.getInstance();
+ guiPackage.updateCurrentNode();
+ JMeterTreeNode treeNode = findFirstNodeOfType(AbstractThreadGroup.class);
+ if (treeNode == null) {
+ LOGGER.info("No AbstractThreadGroup found, potentially empty plan, creating a new plan");
+ createTestPlan(e, request, commentText);
+ } else {
+ JMeterTreeNode currentNode = guiPackage.getCurrentNode();
+ Object userObject = currentNode.getUserObject();
+ if (userObject instanceof Controller && !(userObject instanceof ReplaceableController)) {
+ LOGGER.info("Newly created element will be placed under current selected node {}",
+ currentNode.getName());
+ addToTestPlan(currentNode, request, commentText);
+ } else {
+ LOGGER.info(
+ "Newly created element will be placed under first AbstractThreadGroup node {}",
+ treeNode.getName());
+ addToTestPlan(treeNode, request, commentText);
+ }
+ }
+ statusText.setText(JMeterUtils.getResString("curl_create_success"));
+ }
+ catch (Exception ex) {
+ LOGGER.error("Error creating test plan from cURL command:{}, error:{}", commandsList.get(i),
+ ex.getMessage(), ex);
+ statusText.setText(
+ MessageFormat.format(JMeterUtils.getResString("curl_create_failure"), ex.getMessage()));
+ statusText.setForeground(Color.RED);
+ break;
}
}
- statusText.setText(JMeterUtils.getResString("curl_create_success"));
} catch (Exception ex) {
- LOGGER.error("Error creating test plan from cURL command:{}, error:{}", curlCommand, ex.getMessage(), ex);
- statusText.setText(MessageFormat.format(JMeterUtils.getResString("curl_create_failure"), ex.getMessage()));
+ statusText.setText(
+ MessageFormat.format(JMeterUtils.getResString("curl_create_failure"), ex.getMessage()));
statusText.setForeground(Color.RED);
}
}
}
- private void addToTestPlan(final JMeterTreeNode currentNode, Request request)
- throws MalformedURLException {
- final HTTPSamplerProxy sampler = createSampler(request);
+
+ public List<Request> parseCommands(boolean isReadFromFile, List<String> commandsList) {
+ List<Request> requests = new ArrayList<>();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ for (int i = 0; i < commandsList.size(); i++) {
+ try {
+ BasicCurlParser.Request q = basicCurlParser.parse(commandsList.get(i));
+ requests.add(q);
+ LOGGER.info("Parsed CURL command {} into {}", commandsList.get(i), q);
+ } catch (IllegalArgumentException ie) {
+ if (isReadFromFile) {
+ int line = i + 1;
+ LOGGER.error("Error creating test plan from line {} of file, command:{}, error:{}", line,
+ commandsList.get(i), ie.getMessage(), ie);
+ throw new IllegalArgumentException(
+ "Error creating tast plan from file in line " + line + ", see log file");
+ } else {
+ LOGGER.error("Error creating test plan from cURL command:{}, error:{}", commandsList.get(i),
+ ie.getMessage(), ie);
+ throw ie;
+ }
+ }
+ }
+ return requests;
+ }
+
+ private void addToTestPlan(final JMeterTreeNode currentNode, Request request,String statusText) throws MalformedURLException {
+ final HTTPSamplerProxy sampler = createSampler(request,statusText);
JMeterTreeModel treeModel = GuiPackage.getInstance().getTreeModel();
JMeterUtils.runSafe(true, () -> {
try {
- // We get the HeaderManager before adding component otherwise addComponent would remove it
+ boolean canAddAuthManagerInHttpRequest = false;
+ boolean canAddDnsServer=false;
+ boolean canAddDnsResolver=false;
+ if (!request.getAuthorization().getUser().isEmpty()) {
+ JMeterTreeNode jMeterTreeNodeAuth = findFirstNodeOfType(AuthManager.class);
+ if (jMeterTreeNodeAuth == null) {
+ AuthManager authManager = new AuthManager();
+ createAuthManager(request, authManager);
+ treeModel.addComponent(authManager, currentNode);
+ } else {
+ AuthManager authManager = (AuthManager) jMeterTreeNodeAuth.getTestElement();
+ if (canUpdateAuthManagerInThreadGroup(request, authManager)) {
+ createAuthManager(request, authManager);
+ } else {
+ canAddAuthManagerInHttpRequest = canAddAuthManagerInHttpRequest(request, authManager);
+ }
+ }
+ }
+ if (!request.getDnsServers().isEmpty()) {
+ DNSCacheManager dnsCacheManager = findNodeOfTypeDnsCacheManagerByType(false);
+ if ( dnsCacheManager == null) {
+ dnsCacheManager=new DNSCacheManager();
+ createDnsServer(request, dnsCacheManager);
+ treeModel.addComponent(dnsCacheManager, currentNode);
+ } else {
+ canAddDnsServer=canAddDnsServerInHttpRequest(request, dnsCacheManager);
+ }
+ }
+ if (request.getDnsResolver()!=null) {
+ DNSCacheManager dnsCacheManager = findNodeOfTypeDnsCacheManagerByType(true);
+ if (dnsCacheManager == null) {
+ dnsCacheManager=new DNSCacheManager();
+ createDnsResolver(request, dnsCacheManager);
+ treeModel.addComponent(dnsCacheManager, currentNode);
+ } else {
+ canAddDnsResolver=canAddDnsResolverInHttpRequest(request, dnsCacheManager);
+ }
+ }
+ if (!request.getCookies(request.getUrl()).isEmpty() || !request.getFilepathCookie().isEmpty()
+ || (!request.getCookieInHeaders(request.getUrl()).isEmpty()&&uploadCookiesCheckBox.isSelected())) {
+ JMeterTreeNode jMeterTreeNodeCookie = findFirstNodeOfType(CookieManager.class);
+ if (jMeterTreeNodeCookie == null) {
+ CookieManager cookieManager = new CookieManager();
+ createCookieManager(cookieManager, request);
+ treeModel.addComponent(cookieManager, currentNode);
+ } else {
+ CookieManager cookieManager = (CookieManager) jMeterTreeNodeCookie.getTestElement();
+ createCookieManager(cookieManager, request);
+ }
+ }
HeaderManager headerManager = sampler.getHeaderManager();
- //
+ KeystoreConfig keystoreConfig = sampler.getKeystoreConfig();
final JMeterTreeNode newNode = treeModel.addComponent(sampler, currentNode);
treeModel.addComponent(headerManager, newNode);
+ if (request.getCaCert().equals("cert")) {
+ treeModel.addComponent(keystoreConfig, newNode);
+ }
+ if (canAddAuthManagerInHttpRequest) {
+ AuthManager authManager = new AuthManager();
+ createAuthManager(request, authManager);
+ treeModel.addComponent(authManager, newNode);
+ }
+ if (canAddDnsServer) {
+ DNSCacheManager dnsCacheManager=new DNSCacheManager();
+ createDnsServer(request, dnsCacheManager);
+ treeModel.addComponent(dnsCacheManager, newNode);
+ }
+ if (canAddDnsResolver) {
+ DNSCacheManager dnsCacheManager=new DNSCacheManager();
+ createDnsResolver(request, dnsCacheManager);
+ treeModel.addComponent(dnsCacheManager, newNode);
+ }
} catch (IllegalUserActionException ex) {
LOGGER.error("Error placing sampler", ex);
JMeterUtils.reportErrorToUser(ex.getMessage());
}
});
}
+
+ @Override
+ public Set<String> getActionNames() {
+ return commands;
+ }
+
+ @Override
+ public JMenu[] getTopLevelMenus() {
+ return new JMenu[0];
+ }
+
+ @Override
+ public boolean localeChanged(MenuElement menu) {
+ return false;
+ }
+
+ @Override
+ public void localeChanged() {
+ // NOOP
+ }
+
+ public List<String> readFromFile(String pathname) throws IOException {
+ String encoding = StandardCharsets.UTF_8.name();
+ File file = new File(pathname);
+ return FileUtils.readLines(file, encoding);
+ }
+
+ public List<String> readFromTextPanel(String commands) {
+ String[] cs = commands.split("curl");
+ List<String> s = new ArrayList<>();
+ for (int i = 1; i < cs.length; i++) {
+ s.add("curl " + cs[i].trim());
+ }
+ return s;
+ }
+
+ public String createCommentText(Request request) {
+ StringBuilder commentText = new StringBuilder();
+ if (!request.getOptionsIgnored().isEmpty()) {
+ for (String s : request.getOptionsIgnored()) {
+ commentText.append("--"+s + " ");
+ }
+ commentText.append("ignoring; ");
+ }
+ if (!request.getOptionsInProperties().isEmpty()) {
+ for (String s : request.getOptionsInProperties()) {
+ commentText.append(s + " ");
+ }
+ commentText.append("configure in jmeter.properties ");
+ }
+ if (request.getLimitRate() != 0) {
+ commentText.append(
+ "Please configure the limit rate in 'httpclient.socket.http.cps' of 'jmeter.properties(374 line), the value is "
+ + request.getLimitRate() + ";");
+ }
+ if (!request.getOptionsNoSupport().isEmpty()) {
+ for (String s : request.getOptionsNoSupport()) {
+ commentText.append("--"+s + " ");
+ }
+ commentText.append("not supported; ");
+ }
+ if (request.getNoproxy()!=null) {
+ commentText.append("Please configure noproxy list in terminal and restart JMeter. ");
+ commentText.append("Look: https://jmeter.apache.org/usermanual/get-started.html#proxy_server");
+ }
+ if (!request.getCaCert().isEmpty()) {
+ commentText.append("Please configure the SSL file with CA certificates in 'SSL configuration' of 'system.properties(49 line)'. ");
+ commentText.append("Look: https://jmeter.apache.org/usermanual/properties_reference.html#ssl_config");
+ }
+ return commentText.toString();
+ }
}
diff --git a/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java b/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
index fbb8860..260fa2b 100644
--- a/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
+++ b/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
@@ -45,6 +45,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.config.Argument;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.ConfigTestElement;
+import org.apache.jmeter.config.KeystoreConfig;
import org.apache.jmeter.engine.event.LoopIterationEvent;
import org.apache.jmeter.gui.Replaceable;
import org.apache.jmeter.protocol.http.control.AuthManager;
@@ -112,7 +113,8 @@ public abstract class HTTPSamplerBase extends AbstractSampler
"org.apache.jmeter.protocol.http.gui.DNSCachePanel",
"org.apache.jmeter.protocol.http.gui.AuthPanel",
"org.apache.jmeter.protocol.http.gui.CacheManagerGui",
- "org.apache.jmeter.protocol.http.gui.CookiePanel"
+ "org.apache.jmeter.protocol.http.gui.CookiePanel",
+ "org.apache.jmeter.testbeans.gui.TestBeanGUI"
));
//+ JMX names - do not change
@@ -122,6 +124,10 @@ public abstract class HTTPSamplerBase extends AbstractSampler
public static final String COOKIE_MANAGER = "HTTPSampler.cookie_manager"; // $NON-NLS-1$
+ public static final String KEYSTORE_CONFIG = "HTTPSampler.keystore_configuration"; // $NON-NLS-1$
+
+ public static final String SAMPLE_TIMEOUT = "HTTPSampler.sample_timeout"; // $NON-NLS-1$
+
public static final String CACHE_MANAGER = "HTTPSampler.cache_manager"; // $NON-NLS-1$
public static final String HEADER_MANAGER = "HTTPSampler.header_manager"; // $NON-NLS-1$
@@ -684,6 +690,13 @@ public abstract class HTTPSamplerBase extends AbstractSampler
this.getArguments().addArgument(arg);
}
+ public void addNonEncodedArgument(String name, String value, String metadata, String contentType) {
+ HTTPArgument arg = new HTTPArgument(name, value, metadata, false);
+ arg.setContentType(contentType);
+ arg.setAlwaysEncoded(false);
+ this.getArguments().addArgument(arg);
+ }
+
public void addArgument(String name, String value) {
this.getArguments().addArgument(new HTTPArgument(name, value));
}
@@ -708,7 +721,9 @@ public abstract class HTTPSamplerBase extends AbstractSampler
setAuthManager((AuthManager) el);
} else if (el instanceof DNSCacheManager) {
setDNSResolver((DNSCacheManager) el);
- } else {
+ } else if (el instanceof KeystoreConfig) {
+ setKeystoreConfigProperty((KeystoreConfig) el);
+ } else {
super.addTestElement(el);
}
}
@@ -831,22 +846,42 @@ public abstract class HTTPSamplerBase extends AbstractSampler
return getPropertyAsString(PROXYSCHEME, HTTPHCAbstractImpl.PROXY_SCHEME);
}
+ public void setProxyScheme(String schema) {
+ setProperty(PROXYSCHEME, schema);
+ }
+
public String getProxyHost() {
return getPropertyAsString(PROXYHOST);
}
+ public void setProxyHost(String host) {
+ setProperty(PROXYHOST, host);
+ }
+
public int getProxyPortInt() {
return getPropertyAsInt(PROXYPORT, 0);
}
+ public void setProxyPortInt(String port) {
+ setProperty(PROXYPORT, port);
+ }
+
public String getProxyUser() {
return getPropertyAsString(PROXYUSER);
}
+ public void setProxyUser(String user) {
+ setProperty(PROXYUSER, user);
+ }
+
public String getProxyPass() {
return getPropertyAsString(PROXYPASS);
}
+ public void setProxyPass(String pass) {
+ setProperty(PROXYPASS, pass);
+ }
+
// gets called from ctor, so has to be final
public final void setArguments(Arguments value) {
setProperty(new TestElementProperty(ARGUMENTS, value));
@@ -926,6 +961,21 @@ public abstract class HTTPSamplerBase extends AbstractSampler
private void setCacheManagerProperty(CacheManager value) {
setProperty(new TestElementProperty(CACHE_MANAGER, value));
}
+ private void setKeystoreConfigProperty(KeystoreConfig value) {
+ setProperty(new TestElementProperty(KEYSTORE_CONFIG, value));
+ }
+
+ public void setKeystoreConfig(KeystoreConfig value) {
+ KeystoreConfig mgr = getKeystoreConfig();
+ if (mgr != null && log.isWarnEnabled()) {
+ log.warn("Existing KeystoreConfig {} superseded by {}", mgr.getName(), value.getName());
+ }
+ setKeystoreConfigProperty(value);
+ }
+
+ public KeystoreConfig getKeystoreConfig() {
+ return (KeystoreConfig) getProperty(KEYSTORE_CONFIG).getObjectValue();
+ }
public void setCacheManager(CacheManager value) {
CacheManager mgr = getCacheManager();
diff --git a/test/src/org/apache/jmeter/curl/BasicCurlParserTest.java b/test/src/org/apache/jmeter/curl/BasicCurlParserTest.java
index 4b1df35..b4c3f6c 100644
--- a/test/src/org/apache/jmeter/curl/BasicCurlParserTest.java
+++ b/test/src/org/apache/jmeter/curl/BasicCurlParserTest.java
@@ -18,15 +18,28 @@
package org.apache.jmeter.curl;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jmeter.protocol.http.control.Cookie;
import org.apache.jmeter.protocol.http.curl.BasicCurlParser;
import org.junit.Assert;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
/**
* @since 5.1
*/
public class BasicCurlParserTest {
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
/**
*
*/
@@ -43,9 +56,14 @@ public class BasicCurlParserTest {
BasicCurlParser basicCurlParser = new BasicCurlParser();
BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
Assert.assertEquals("http://jmeter.apache.org/", request.getUrl());
- Assert.assertEquals(6, request.getHeaders().size());
+ Assert.assertEquals(5, request.getHeaders().size());
Assert.assertTrue(request.isCompressed());
Assert.assertEquals("GET", request.getMethod());
+ String resParser = "Request [compressed=true, url=http://jmeter.apache.org/, method=GET, headers={User-Agent=Mozilla/5.0 "
+ + "(Macintosh; Intel Mac OS X 10.11; rv:63.0) Gecko/20100101 Firefox/63.0, Accept=text/html,application/xhtml+xml,"
+ + "application/xml;q=0.9,*/*;q=0.8, Accept-Language=en-US,en;q=0.5, DNT=1, "
+ + "Upgrade-Insecure-Requests=1}]";
+ Assert.assertEquals("The method 'toString' should get all parameters correctly", resParser, request.toString());
}
@Test
@@ -61,7 +79,15 @@ public class BasicCurlParserTest {
Assert.assertEquals("https://jmeter.apache.org/", request.getUrl());
Assert.assertEquals(7, request.getHeaders().size());
Assert.assertTrue(request.isCompressed());
- Assert.assertEquals("GET", request.getMethod());
+ }
+
+ @Test
+ public void testDoubleQuote() {
+ String cmdLine = "curl \"http://jmeter.apache.org/\"";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("The method 'translateCommandline' should get the url correctly When using double quotes, ",
+ "http://jmeter.apache.org/", request.getUrl());
}
@Test
@@ -69,10 +95,9 @@ public class BasicCurlParserTest {
String cmdLine = "curl 'https://jmeter.apache.org/' -H 'Proxy-Connection: keep-alive' "
+ "-H 'Proxy-Authorization: Basic XXXXXXXXX/' -H 'Upgrade-Insecure-Requests: 1' "
+ "-H 'User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko)"
- + " Chrome/70.0.3538.102 Mobile Safari/537.36' "
+ + " Chrome/70.0.3538.102 Mobile Safari/537.36' "
+ "-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' "
- + "-H 'Accept-Encoding: gzip, deflate' "
- + "-H 'Accept-Language: en-US,en;q=0.9,fr;q=0.8'";
+ + "-H 'Accept-Encoding: gzip, deflate' " + "-H 'Accept-Language: en-US,en;q=0.9,fr;q=0.8'";
BasicCurlParser basicCurlParser = new BasicCurlParser();
BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
Assert.assertEquals("https://jmeter.apache.org/", request.getUrl());
@@ -93,8 +118,25 @@ public class BasicCurlParserTest {
}
@Test
+ public void testNullCommand() {
+ String cmdLine = "";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("The method 'translateCommandline' should return 'null' when command is empty, ",
+ "Request [compressed=false, url=null, method=GET, headers={}]", request.toString());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUnbalancedQuotes() {
+ String cmdLine = "curl \"https://jmeter.apache.org/'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ basicCurlParser.parse(cmdLine);
+ Assert.fail("The method 'translateCommandline shouldn't run when the quotes are not balanced,");
+ }
+
+ @Test
public void testPost() {
- String cmdLine = "curl 'https://jmeter.apache.org/test' "
+ String cmdLine = "curl 'https://jmeter.apache.org/test' -X 'POST' "
+ "-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:63.0) Gecko/20100101 Firefox/63.0' -H 'Accept: */*' "
+ "-H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Referer: https://www.example.com/' "
+ "-H 'content-type: application/json;charset=UTF-8' -H 'Origin: https://www.example.com' "
@@ -103,22 +145,502 @@ public class BasicCurlParserTest {
BasicCurlParser basicCurlParser = new BasicCurlParser();
BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
Assert.assertEquals("https://jmeter.apache.org/test", request.getUrl());
- Assert.assertEquals(9, request.getHeaders().size());
+ Assert.assertEquals(8, request.getHeaders().size());
Assert.assertTrue(request.isCompressed());
Assert.assertEquals("POST", request.getMethod());
+ Assert.assertEquals("The method 'getPostData' should return the data correctly",
+ "{\"abc\":\"123\",\"no\":\"matter on sunshine\"}", request.getPostData());
}
- @Test(expected=IllegalArgumentException.class)
+ @Test
+ public void testMethodPut() {
+ String cmdLine = "curl -X 'PUT' 'https://jmeter.apache.org/test' "
+ + "-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:63.0) Gecko/20100101 Firefox/63.0' -H 'Accept: */*' "
+ + "-H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Referer: https://www.example.com/' "
+ + "-H 'content-type: application/json;charset=UTF-8' -H 'Origin: https://www.example.com' "
+ + "-H 'DNT: 1' -H 'Connection: keep-alive' -H 'TE: Trailers'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("PUT", request.getMethod());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
public void testError() {
- String cmdLine = "curl 'https://jmeter.apache.org/' -u -H 'Proxy-Connection: keep-alive' "
+ String cmdLine = "curl 'https://jmeter.apache.org/' --error -H 'Proxy-Connection: keep-alive' "
+ "-H 'Proxy-Authorization: Basic XXXXXXXXX/' "
- + "-H 'Upgrade-Insecure-Requests: 1' "
+ "-H 'User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko)"
- + " Chrome/70.0.3538.102 Mobile Safari/537.36' "
- + "-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' "
- + "-H 'Accept-Encoding: gzip, deflate' "
- + "-H 'Accept-Language: en-US,en;q=0.9,fr;q=0.8'";
+ + " Chrome/70.0.3538.102 Mobile Safari/537.36' "
+ + "-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' "
+ + "-H 'Accept-Encoding: gzip, deflate' " + "-H 'Accept-Language: en-US,en;q=0.9,fr;q=0.8'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ basicCurlParser.parse(cmdLine);
+ }
+
+ @Test
+ public void testUserAgent() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -H 'User-Agent: Mozilla/5.0 (Macintosh;"
+ + " Intel Mac OS X 10.11; rv:63.0) Gecko/20100101 Firefox/63.0' "
+ + "-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' "
+ + "-H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'DNT: 1' "
+ + "-H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -A 'Mozilla/5.0'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser', the quantity of Headers should be 5' ", 5,
+ request.getHeaders().size());
+ Assert.assertEquals("With method 'parser', Headers need to add 'user-agent' with value 'Mozilla/5.0' ",
+ "Mozilla/5.0", request.getHeaders().get("User-Agent"));
+ }
+
+ @Test
+ public void testConnectMax() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -H 'Connection: keep-alive' "
+ + "-H 'Upgrade-Insecure-Requests: 1' --connect-timeout '2'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser' request should contain 'connect-timeout=2'", "2000.0",
+ String.valueOf( request.getConnectTimeout()));
+ }
+
+ @Test
+ public void testAuthorization() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -u 'arun:12345'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals(
+ "With method 'parser',request should contain the parameters of the userneame of authorization", "arun",
+ request.getAuthorization().getUser());
+ Assert.assertEquals(
+ "With method 'parser',request should contain the " + "parameters of the password of authorization",
+ "12345", request.getAuthorization().getPass());
+ }
+
+ @Test
+ public void testAuthorizationMechanismIsDigest() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -u 'arun:12345' --digest";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the mechanism should be 'DIGEST' ", "DIGEST",
+ request.getAuthorization().getMechanism().toString());
+ }
+
+ @Test
+ public void testAuthMechanismIsBasic() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -u 'arun:12345' --basic";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the mechanism should be 'BASIC' ", "BASIC",
+ request.getAuthorization().getMechanism().toString());
+ }
+
+ @Test
+ public void testDefaultAuthMechanism() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -u 'arun:12345'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the mechanism should be 'BASIC' ", "BASIC",
+ request.getAuthorization().getMechanism().toString());
+ }
+
+ @Test
+ public void testCacert() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --cacert 'test.pem' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the cacert need to show a warning' ", "cacert", request.getCaCert());
+ }
+
+ @Test
+ public void testCapath() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --capath 'test.pem' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the cacert need to show a warning' ", "capath", request.getCaCert());
+ }
+
+ @Test
+ public void testCert() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -E 'test.pem' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the cacert need to show a warning' ", "cert", request.getCaCert());
+ }
+
+ @Test
+ public void testCiphers() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --ciphers 'test.pem' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the cacert need to show a warning' ", "ciphers", request.getCaCert());
+ }
+
+ @Test
+ public void testCertStatus() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --cert-status ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the cacert need to show a warning' ", "cert-status",
+ request.getCaCert());
+ }
+
+ @Test
+ public void testCertType() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --cert-type 'test'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the cacert need to show a warning' ", "cert-type",
+ request.getCaCert());
+ }
+
+ @Test
+ public void testData() {
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' --data 'name=test' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the parameters should be name=test' ", "name=test",
+ request.getPostData());
+ }
+
+ @Test
+ public void testDataReadFromFile() throws IOException {
+ String encoding = StandardCharsets.UTF_8.name();
+ File file = tempFolder.newFile("test.txt");
+ FileUtils.writeStringToFile(file, "name=test" + System.lineSeparator(), encoding, true);
+ String pathname = file.getAbsolutePath();
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' --data '@" + pathname + "' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the parameters need to reserve '\n' and '\r' ", "name=test",
+ request.getPostData());
+ }
+ @Test(expected = IllegalArgumentException.class)
+ public void testDataReadFromNonexistentFile() {
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' --data '@test.txt' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ basicCurlParser.parse(cmdLine);
+ Assert.fail("The method 'translateCommandline shouldn't run when the path of file is incorrect");
+ }
+ @Test
+ public void testDataUrlEncodeOneParameterWithoutName() {
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' --data-urlencode 'é' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the parameters need to be encoded' ", "%C3%A9",
+ request.getPostData());
+ }
+ @Test
+ public void testDataUrlEncodeOneParameterWithName() {
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' --data-urlencode 'value=é' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the parameters need to be encoded' ", "value=%C3%A9",
+ request.getPostData());
+ }
+
+ @Test
+ public void testDataUrlEncodeMoreThanOneParameters() {
+ String cmdLine = "curl 'https://postman-echo.com/post' -H 'Content-Type: application/x-www-form-urlencoded'"
+ + " -H 'cache-control: no-cache' --data-urlencode 'foo1=!!!&foo2=???'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the parameters need to be encoded' ",
+ "foo1=%21%21%21%26foo2%3D%3F%3F%3F", request.getPostData());
+ }
+
+ @Test
+ public void testDataUrlEncodeFromFile() throws IOException {
+ String encoding = StandardCharsets.UTF_8.name();
+ File file = tempFolder.newFile("test.txt");
+ FileUtils.writeStringToFile(file, "test", encoding, true);
+ String pathname = file.getAbsolutePath();
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' --data-urlencode 'name@" + pathname + "' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the parameters in the file need to be encoded' ", "name=test",
+ request.getPostData());
+ }
+ @Test
+ public void testDataUrlEncodeWith2AtSymbol() throws IOException {
+ String encoding = StandardCharsets.UTF_8.name();
+ File file = tempFolder.newFile("test.txt");
+ FileUtils.writeStringToFile(file, "test@", encoding, true);
+ String pathname = file.getAbsolutePath();
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' --data-urlencode 'name@" + pathname + "' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the parameters in the file need to be encoded' ", "name=test%40",
+ request.getPostData());
+ }
+
+ @Test
+ public void testDataBinaryReadFromFile() throws IOException {
+ String encoding = StandardCharsets.UTF_8.name();
+ File file = tempFolder.newFile("test.txt");
+ FileUtils.writeStringToFile(file, "name=test" + System.lineSeparator(), encoding, true);
+ String pathname = file.getAbsolutePath();
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' --data-binary '@" + pathname + "' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the parameters need to reserve '\n' and '\r' ",
+ "name=test" + System.lineSeparator(), request.getPostData());
+ }
+
+ @Test
+ public void testForm() {
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' -F 'test=name' -F 'test1=name1' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Map<String, String> res = request.getFormData();
+ Assert.assertEquals("With method 'parser', we should post form data", "name1", res.get("test1"));
+ }
+
+ @Test
+ public void testFormString() {
+ String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
+ + "-H 'cache-control: no-cache' --form-string 'image=@C:\\Test\\test.jpg' ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Map<String, String> res = request.getFormStringData();
+ Assert.assertEquals("With method 'parser', we should post form data", "@C:\\Test\\test.jpg", res.get("image"));
+ }
+
+ @Test
+ public void testGet() {
+ String cmdLine = "curl -X POST \"https://api.imgur.com/3/upload\" "
+ + " -H 'Authorization: Client-ID fb52f2bfa714a36' --data " + "'name=aaa%&lname=bbb' -G";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser', it should put the post data in the url",
+ "https://api.imgur.com/3/upload?name=aaa%&lname=bbb", request.getUrl());
+ Assert.assertEquals("With method 'parser',the method should be 'GET'", "GET", request.getMethod());
+ }
+
+ @Test
+ public void testDnsServer() {
+ String cmdLine = "curl -X POST \"https://api.imgur.com/3/upload\" "
+ + " -H 'Authorization: Client-ID fb52f2bfa714a36' --dns-servers '0.0.0.0,1.1.1.1'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertTrue("With method 'parser', the Dns Server 0.0.0.0 should exist",
+ request.getDnsServers().contains("0.0.0.0"));
+ }
+
+ @Test
+ public void testNotKeepAlive() {
+ String cmdLine = "curl -X POST \"https://api.imgur.com/3/upload\" "
+ + " -H 'Authorization: Client-ID fb52f2bfa714a36' --dns-servers '0.0.0.0,1.1.1.1' --no-keepalive ";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertFalse("With method 'parser', keepalive should be disabled", request.isKeepAlive());
+ }
+
+ @Test
+ public void testProxy() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -x 'https://aa:bb@example.com:8042'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the host of proxy should be 'examole.com'", "example.com",
+ request.getProxyServer().get("servername"));
+ Assert.assertEquals("With method 'parser',the port of proxy should be 8042", "8042",
+ request.getProxyServer().get("port"));
+ Assert.assertEquals("With method 'parser',the scheme of proxy should be https", "https",
+ request.getProxyServer().get("scheme"));
+ Assert.assertEquals("With method 'parser',the username of proxy should be aa", "aa",
+ request.getProxyServer().get("username"));
+ Assert.assertEquals("With method 'parser',the password of proxy should be aa", "bb",
+ request.getProxyServer().get("password"));
+ }
+
+ @Test
+ public void testProxyDefaultPort() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -x 'https://example.com'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the default port of proxy should be 1080", "1080",
+ request.getProxyServer().get("port"));
+ }
+
+ @Test
+ public void testProxyUser() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --proxy '201.36.208.19:3128' -U 'aa:bb'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser',the username of proxy should be aa", "aa",
+ request.getProxyServer().get("username"));
+ Assert.assertEquals("With method 'parser',the password of proxy should be aa", "bb",
+ request.getProxyServer().get("password"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testProxyUriIncorrectFormat() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -x 'https://xxxx.xxx?xxx=xxx|xxxx|'";
BasicCurlParser basicCurlParser = new BasicCurlParser();
basicCurlParser.parse(cmdLine);
+ Assert.fail(
+ "The method 'translateCommandline shouldn't run when the uri of proxy is not in the correct format");
+ }
+
+ @Test
+ public void testMaxTime() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -m '2'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser', max time of all the operation should be 200", "2000.0",
+ String.valueOf( request.getMaxTime()));
+ }
+
+ @Test
+ public void testReferer() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --referer 'www.baidu.com'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser', the refer page information should be set in http Header",
+ "www.baidu.com", request.getHeaders().get("Referer"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testStringtoCookie() {
+ String cookieStr = "name=Tom;password=123456";
+ String url = "api.imgur.com/3/upload";
+ BasicCurlParser.stringToCookie(cookieStr, url);
+ }
+ @Test
+ public void testCookie() {
+ String cmdLine = "curl -X POST \"https://api.imgur.com/3/upload\" -b 'name=Tom;password=123456'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ List<Cookie>cookies=new ArrayList<>();
+ Cookie c1=new Cookie();
+ c1.setDomain("api.imgur.com");
+ c1.setName("name");
+ c1.setValue("Tom");
+ c1.setPath("/3/upload");
+ Cookie c2=new Cookie();
+ c2.setDomain("api.imgur.com");
+ c2.setName("password");
+ c2.setValue("123456");
+ c2.setPath("/3/upload");
+ cookies.add(c1);
+ cookies.add(c2);
+ Assert.assertTrue("With method 'parser', the cookie should be set in CookieManager",
+ request.getCookies("https://api.imgur.com/3/upload").contains(c1));
+ Assert.assertTrue("With method 'parser', the cookie should be set in CookieManager",
+ request.getCookies("https://api.imgur.com/3/upload").contains(c2));
+ Assert.assertEquals("With method 'parser', the cookie should be set in CookieManager", 2,
+ request.getCookies("https://api.imgur.com/3/upload").size());
+ }
+ @Test
+ public void testCookieFromFile() throws IOException {
+ File file = tempFolder.newFile("test.txt");
+ String pathname = file.getAbsolutePath();
+ String cmdLine = "curl -X POST \"https://api.imgur.com/3/upload\" -b '" + pathname + "'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("With method 'parser', the file of cookie should be uploaded in CookieManager",
+ file.getAbsolutePath(), request.getFilepathCookie());}
+ @Test
+ public void testCookieInHeader() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -H 'cookie: PHPSESSID=testphpsessid;a=b' --compressed";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ List<Cookie>cookies=request.getCookieInHeaders("http://jmeter.apache.org/");
+ Cookie c1=new Cookie();
+ c1.setDomain("jmeter.apache.org");
+ c1.setName("a");
+ c1.setValue("b");
+ c1.setPath("/");
+ Assert.assertEquals("Just static cookie in header can be added in CookieManager", c1, cookies.get(0));
+ Assert.assertEquals("Just static cookie in header can be added in CookieManager", 1, cookies.size());
+ }
+ @Test
+ public void testIgnoreOptions() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --include --keepalive-time '20'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ List<String> listOptions=request.getOptionsIgnored();
+ Assert.assertTrue("The list of ignored options should contain 'include'", listOptions.contains("include"));
+ Assert.assertTrue("The list of ignored options should contain 'keepalive-time'", listOptions.contains("keepalive-time"));
+ }
+
+ @Test
+ public void testHead() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --head";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("The method should be HEAD","HEAD", request.getMethod());
+ }
+
+ @Test
+ public void testInterface() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --interface 'etho'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("The interface should to be etho","etho", request.getInterfaceName());
+ }
+
+ @Test
+ public void testResolver() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --resolve 'moonagic.com:443:127.0.0.2'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("The resolve DNS should be 'moonagic.com:443:127.0.0.2'", "moonagic.com:443:127.0.0.2",
+ request.getDnsResolver());
+ }
+
+ @Test
+ public void testLimitRate() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --limit-rate '1g'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("The limit rate should be 1024000000",1024000000,request.getLimitRate());
+ cmdLine = "curl 'http://jmeter.apache.org/' --limit-rate '171k'";
+ request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("The limit rate should be 175104",175104,request.getLimitRate());
+ cmdLine = "curl 'http://jmeter.apache.org/' --limit-rate '54M'";
+ request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("The limit rate should be 55296000",55296000,request.getLimitRate());
+ }
+
+ @Test
+ public void testNoproxy() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --noproxy 'localhost'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertEquals("No Proxy server should be localhost", "localhost",
+ request.getNoproxy());
+ }
+
+ @Test
+ public void testConfigureInProperties() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' --max-redirs 'b'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertTrue("Option max-redirs should show warning",
+ request.getOptionsInProperties().contains("--max-redirs is in 'httpsampler.max_redirects(1062 line)'"));
+ }
+
+ @Test
+ public void testNoSupport() {
+ String cmdLine = "curl 'http://jmeter.apache.org/' -x 'https://aa:bb@example.com:8042' --proxy-ntlm";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ Assert.assertTrue("Option proxy-ntlm should show warning",
+ request.getOptionsNoSupport().contains("proxy-ntlm"));
+ }
+
+ @Test
+ public void testIsValidCookie() {
+ String str="a=b;c=d";
+ Assert.assertTrue("The string should be cookies",BasicCurlParser.isValidCookie(str));
+ str="test.txt";
+ Assert.assertFalse("The string should be filename",BasicCurlParser.isValidCookie(str));
}
}
diff --git a/test/src/org/apache/jmeter/gui/action/ParseCurlCommandActionTest.java b/test/src/org/apache/jmeter/gui/action/ParseCurlCommandActionTest.java
new file mode 100644
index 0000000..f783f06
--- /dev/null
+++ b/test/src/org/apache/jmeter/gui/action/ParseCurlCommandActionTest.java
@@ -0,0 +1,605 @@
+/*
+ * 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.gui.action;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import javax.swing.JCheckBox;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jmeter.protocol.http.control.AuthManager;
+import org.apache.jmeter.protocol.http.control.AuthManager.Mechanism;
+import org.apache.jmeter.protocol.http.control.Authorization;
+import org.apache.jmeter.protocol.http.control.CookieManager;
+import org.apache.jmeter.protocol.http.control.DNSCacheManager;
+import org.apache.jmeter.protocol.http.control.HeaderManager;
+import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui;
+import org.apache.jmeter.protocol.http.curl.BasicCurlParser;
+import org.apache.jmeter.protocol.http.curl.BasicCurlParser.Request;
+import org.apache.jmeter.protocol.http.gui.action.ParseCurlCommandAction;
+import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory;
+import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
+import org.apache.jmeter.testelement.TestElement;
+import org.apache.jmeter.testelement.TestPlan;
+import org.apache.jmeter.threads.ThreadGroup;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.collections.HashTree;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class ParseCurlCommandActionTest {
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ @Test
+ public void testCreateCommentText() {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ String cmdLine = "curl 'http://jmeter.apache.org/' --max-redirs 'b'";
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+ String comment = p.createCommentText(request);
+ assertEquals("Http request should can be set the right comment",
+ "--max-redirs is in 'httpsampler.max_redirects(1062 line)' configure in jmeter.properties ", comment);
+ cmdLine = "curl 'http://jmeter.apache.org/' --include --keepalive-time '20'";
+ request = basicCurlParser.parse(cmdLine);
+ comment = p.createCommentText(request);
+ assertEquals("Http request should can be set the right comment", "--include --keepalive-time ignoring;",
+ comment.trim());
+ cmdLine = "curl 'http://jmeter.apache.org/' -x 'https://aa:bb@example.com:8042' --proxy-ntlm";
+ basicCurlParser = new BasicCurlParser();
+ request = basicCurlParser.parse(cmdLine);
+ comment = p.createCommentText(request);
+ assertEquals("Http request should can be set the right comment", "--proxy-ntlm not supported; ", comment);
+ cmdLine = "curl 'http://jmeter.apache.org/' --include --keepalive-time '20'";
+ basicCurlParser = new BasicCurlParser();
+ request = basicCurlParser.parse(cmdLine);
+ comment = p.createCommentText(request);
+ assertEquals("Http request should can be set the right comment", "--include --keepalive-time ignoring;",
+ comment.trim());
+ cmdLine = "curl 'http://jmeter.apache.org/'";
+ basicCurlParser = new BasicCurlParser();
+ request = basicCurlParser.parse(cmdLine);
+ comment = p.createCommentText(request);
+ assertTrue("Http request should can't be set the right comment", comment.isEmpty());
+ cmdLine = "curl 'http://jmeter.apache.org/' --limit-rate '54M'";
+ basicCurlParser = new BasicCurlParser();
+ request = basicCurlParser.parse(cmdLine);
+ comment = p.createCommentText(request);
+ assertTrue(comment.trim().contains("Please configure the limit rate in 'httpclient.socket.http.cps'"));
+ cmdLine = "curl 'http://jmeter.apache.org/' --noproxy ' localhost'";
+ basicCurlParser = new BasicCurlParser();
+ request = basicCurlParser.parse(cmdLine);
+ comment = p.createCommentText(request);
+ assertTrue(comment.trim().contains("Please configure noproxy list in terminal and restart JMeter."));
+ cmdLine = "curl 'http://jmeter.apache.org/' --cacert '<CA certificate>'";
+ basicCurlParser = new BasicCurlParser();
+ request = basicCurlParser.parse(cmdLine);
+ comment = p.createCommentText(request);
+ assertTrue(comment.trim().contains("Please configure the SSL file with CA certificates"));
+ }
+
+ @Test
+ public void testReadCurlCommandsFromTextPanel() {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ String cmdLine = "curl 'http://jmeter.apache.org/' --max-redirs 'b' "
+ + "curl 'http://jmeter.apache.org/' --include --keepalive-time '20'";
+ List<String> commands = p.readFromTextPanel(cmdLine);
+ assertTrue("Curl commands should be saved in list",
+ commands.contains("curl 'http://jmeter.apache.org/' --max-redirs 'b'"));
+ assertTrue("Curl commands should be saved in list",
+ commands.contains("curl 'http://jmeter.apache.org/' --include --keepalive-time '20'"));
+ assertTrue("The size of list should be 2", commands.size() == 2);
+ }
+
+ @Test
+ public void testReadCurlCommandsFromFile() throws IOException {
+ String encoding = StandardCharsets.UTF_8.name();
+ File file = tempFolder.newFile("test.txt");
+ String cmdLine = "curl 'http://jmeter.apache.org/' --max-redirs 'b'" + System.lineSeparator()
+ + "curl 'http://jmeter.apache.org/' --include --keepalive-time '20'";
+ FileUtils.writeStringToFile(file, cmdLine, encoding, true);
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ List<String> commands = p.readFromFile(file.getAbsolutePath());
+ assertTrue("Curl commands should be saved in list",
+ commands.contains("curl 'http://jmeter.apache.org/' --max-redirs 'b'"));
+ assertTrue("Curl commands should be saved in list",
+ commands.contains("curl 'http://jmeter.apache.org/' --include --keepalive-time '20'"));
+ assertTrue("The size of list should be 2", commands.size() == 2);
+ }
+
+ @Test
+ public void testParseCommands() {
+ // commands from textpanel
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ String cmdLine = "curl 'http://jmeter.apache.org/' --max-redirs 'b' "
+ + "curl 'http://jmeter.apache.org/' --include --keepalive-time '20'";
+ List<String> commands = p.readFromTextPanel(cmdLine);
+ List<Request> requests = p.parseCommands(false, commands);
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request1 = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --max-redirs 'b'");
+ assertEquals("The command line should be parsed in turn", request1.toString(), requests.get(0).toString());
+ assertTrue("The size of list should be 2", requests.size() == 2);
+
+ // commands from file
+ cmdLine = "curl 'http://jmeter.apache.org/' --max-redirs 'b'" + System.lineSeparator()
+ + "curl 'http://jmeter.apache.org/' --include --keepalive-time '20'";
+ commands = p.readFromTextPanel(cmdLine);
+ requests = p.parseCommands(true, commands);
+ request1 = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --max-redirs 'b'");
+ assertTrue("The command line should be parsed in turn", request1.toString().equals(requests.get(0).toString()));
+ assertTrue("The size of list should be 2", requests.size() == 2);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandsException() {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ String cmdLine = "curl 'http://jmeter.apache.org/' --max-redir 'b' "
+ + "curl 'http://jmeter.apache.org/' --include --keepalive-time '20'";
+ List<String> commands = p.readFromTextPanel(cmdLine);
+ p.parseCommands(false, commands);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandsException2() {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ String cmdLine = "curl 'http://jmeter.apache.org/' --max-redir 'b'" + System.lineSeparator()
+ + "curl 'http://jmeter.apache.org/' --include --keepalive-time '20'";
+ List<String> commands = p.readFromTextPanel(cmdLine);
+ p.parseCommands(true, commands);
+ }
+
+ @Test
+ public void testCreateProxyServer()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ HTTPSamplerProxy httpSampler = (HTTPSamplerProxy) HTTPSamplerFactory
+ .newInstance(HTTPSamplerFactory.DEFAULT_CLASSNAME);
+ httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
+ httpSampler.setProperty(TestElement.NAME, "HTTP Request");
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -x 'https://aa:bb@example.com:8042'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, HTTPSamplerProxy.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("createProxyServer", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, httpSampler };
+ method.invoke(p, objs);
+ assertEquals("proxy host should be set in httpsampler", "example.com", httpSampler.getProxyHost());
+ assertEquals("proxy user should be set in httpsampler", "aa", httpSampler.getProxyUser());
+ assertEquals("proxy pass should be set in httpsampler", "bb", httpSampler.getProxyPass());
+ assertEquals("proxy scheme should be set in httpsampler", "https", httpSampler.getProxyScheme());
+ assertEquals("proxy host should be set in httpsampler", "example.com", httpSampler.getProxyHost());
+ assertTrue("The command line should be parsed in turn", httpSampler.getProxyPortInt() == 8042);
+ }
+
+ @Test
+ public void testCreateSampler()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, IOException {
+ // test proxy in httpsampler
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -x 'https://aa:bb@example.com:8042'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, String.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("createSampler", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, "" };
+ HTTPSamplerProxy httpSampler = (HTTPSamplerProxy) method.invoke(p, objs);
+ assertEquals("proxy scheme should be set in httpsampler", "https", httpSampler.getProxyScheme());
+ assertEquals("proxy host should be set in httpsampler", "example.com", httpSampler.getProxyHost());
+ assertTrue("The command line should be parsed in turn", httpSampler.getProxyPortInt() == 8042);
+ assertEquals("path should be set in httpsampler", httpSampler.getPath(), "/");
+ assertEquals("domain should be set in httpsampler", "jmeter.apache.org", httpSampler.getDomain());
+ assertEquals("method should be set in httpsampler", "GET", httpSampler.getMethod());
+
+ // test post data in httpsampler
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --data 'name=test'");
+ request.setInterfaceName("interface_name");
+ objs = new Object[] { request, "" };
+ httpSampler = (HTTPSamplerProxy) method.invoke(p, objs);
+ assertEquals("method should be set in httpsampler", "POST", httpSampler.getMethod());
+ assertEquals("data should be set in httpsampler", "name=test",
+ httpSampler.getArguments().getArgument(0).toString());
+
+ // test form data in httpsampler(upload data)
+ request = basicCurlParser
+ .parse("curl 'http://jmeter.apache.org/' -F 'test=name;type=text/foo' -F 'test1=name1'");
+ objs = new Object[] { request, "" };
+ httpSampler = (HTTPSamplerProxy) method.invoke(p, objs);
+ assertEquals("method should be set in httpsampler", "POST", httpSampler.getMethod());
+ assertEquals("form name should be set in httpsampler", "test",
+ httpSampler.getArguments().getArgument(0).getName());
+ assertEquals("form value should be set in httpsampler", "name",
+ httpSampler.getArguments().getArgument(0).getValue());
+ assertEquals("form name should be set in httpsampler", "test1",
+ httpSampler.getArguments().getArgument(1).getName());
+ assertEquals("form value should be set in httpsampler", "name1",
+ httpSampler.getArguments().getArgument(1).getValue());
+
+ // test form data in httpsampler(upload file)
+ File file = tempFolder.newFile("test.txt");
+ String filePath = file.getAbsolutePath();
+ request = basicCurlParser.parse(
+ "curl 'http://jmeter.apache.org/' -F 'c=@" + filePath + ";type=text/foo' -F 'c1=@" + filePath + "'");
+ objs = new Object[] { request, "" };
+ httpSampler = (HTTPSamplerProxy) method.invoke(p, objs);
+ assertEquals("form name should be set in httpsampler", "c", httpSampler.getHTTPFiles()[0].getParamName());
+ assertEquals("form name should be set in httpsampler", filePath, httpSampler.getHTTPFiles()[0].getPath());
+ assertEquals("form name should be set in httpsampler", "c1", httpSampler.getHTTPFiles()[1].getParamName());
+
+ // test form data in httpsampler
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --form-string 'c=@test.txt;type=text/foo'");
+ objs = new Object[] { request, "" };
+ httpSampler = (HTTPSamplerProxy) method.invoke(p, objs);
+ assertEquals("form name should be set in httpsampler", "c",
+ httpSampler.getArguments().getArgument(0).getName());
+ assertEquals("form value should be set in httpsampler", "@test.txt;type=text/foo",
+ httpSampler.getArguments().getArgument(0).getValue());
+ }
+
+ @Test
+ public void testDataFormException() throws NoSuchMethodException, SecurityException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ HTTPSamplerProxy httpSampler = (HTTPSamplerProxy) HTTPSamplerFactory
+ .newInstance(HTTPSamplerFactory.DEFAULT_CLASSNAME);
+ httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
+ httpSampler.setProperty(TestElement.NAME, "HTTP Request");
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser
+ .parse("curl 'http://jmeter.apache.org/' -F 'test=name' --data 'fname=a&lname=b'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, HTTPSamplerProxy.class };
+ Object[] objs = new Object[] { request, httpSampler };
+ try {
+ Method method = parseCurlCommandAction.getDeclaredMethod("setFormData", classes);
+ method.setAccessible(true);
+ method.invoke(p, objs);
+ fail();
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof IllegalArgumentException) {
+ assertTrue(cause.getMessage().contains("--form and --data can't appear in the same command"));
+ }
+ }
+ }
+
+ @Test
+ public void testCreateHttpRequest()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ ThreadGroup threadGroup = new ThreadGroup();
+ TestPlan testPlan = new TestPlan();
+ HashTree tree = new HashTree();
+ HashTree testPlanHT = tree.add(testPlan);
+ HashTree threadGroupHT = testPlanHT.add(threadGroup);
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -E '<CA certificate>'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, HashTree.class, String.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("createHttpRequest", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, threadGroupHT, "comment" };
+ HTTPSamplerProxy httpSampler = (HTTPSamplerProxy) method.invoke(p, objs);
+ assertEquals("path should be set in httpsampler", httpSampler.getPath(), "/");
+ assertEquals("domain should be set in httpsampler", "jmeter.apache.org", httpSampler.getDomain());
+ assertEquals("method should be set in httpsampler", "GET", httpSampler.getMethod());
+ }
+
+ @Test
+ public void testConfigureTimeout() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -m '20' --connect-timeout '1'");
+ HTTPSamplerProxy httpSampler = (HTTPSamplerProxy) HTTPSamplerFactory
+ .newInstance(HTTPSamplerFactory.DEFAULT_CLASSNAME);
+ httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
+ httpSampler.setProperty(TestElement.NAME, "HTTP Request");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, HTTPSamplerProxy.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("configureTimeout", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, httpSampler };
+ method.invoke(p, objs);
+ assertTrue("max connection time should be 1000", httpSampler.getConnectTimeout() == 1000);
+ assertTrue("max response time should be 19000", httpSampler.getResponseTimeout() == 19000);
+ }
+
+ @Test
+ public void testCreateHeaderManager()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse(
+ "curl 'http://jmeter.apache.org/' -H 'Content-Type: application/x-www-form-urlencoded' --compressed");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("createHeaderManager", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request };
+ HeaderManager headerManager = (HeaderManager) method.invoke(p, objs);
+ assertEquals("header should be set in HeaderManager", "Content-Type", headerManager.get(0).getName());
+ assertEquals("header should be set in HeaderManager", "application/x-www-form-urlencoded",
+ headerManager.get(0).getValue());
+ assertEquals("header should be set in HeaderManager", "Accept-Encoding", headerManager.get(1).getName());
+ assertEquals("header should be set in HeaderManager", "gzip, deflate", headerManager.get(1).getValue());
+ }
+
+ @Test
+ public void testCreateAuthManager()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ AuthManager authManager = new AuthManager();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -u 'user:passwd'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, AuthManager.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("createAuthManager", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, authManager };
+ HeaderManager headerManager = (HeaderManager) method.invoke(p, objs);
+ assertEquals("the username of Authorization should be set in AuthManager", "user",
+ authManager.get(0).getUser());
+ assertEquals("the password of Authorization should be set in AuthManager", "passwd",
+ authManager.get(0).getPass());
+ }
+
+ @Test
+ public void testCanAddAuthManagerInHttpRequest()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ AuthManager authManager = new AuthManager();
+ Authorization authorization = new Authorization();
+ authorization.setPass("passwd");
+ authorization.setUser("user");
+ authorization.setURL("http://jmeter.apache.org/");
+ authorization.setMechanism(Mechanism.BASIC);
+ authManager.addAuth(authorization);
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -u 'user:passwd'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, AuthManager.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("canAddAuthManagerInHttpRequest", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, authManager };
+ assertFalse("When AuthManager contains this authorization, shouldn't add a AuthManager in Http Request",
+ (boolean) method.invoke(p, objs));
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -u 'user1:passwd1'");
+ objs = new Object[] { request, authManager };
+ assertTrue("When AuthManager contains this url, but the username or password isn't the same,"
+ + "should add a AuthManager in Http Request", (boolean) method.invoke(p, objs));
+ }
+
+ @Test
+ public void testCanUpdateAuthManagerInThreadGroupt()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ AuthManager authManager = new AuthManager();
+ Authorization authorization = new Authorization();
+ authorization.setPass("passwd");
+ authorization.setUser("user");
+ authorization.setURL("http://jmeter.apache.org/");
+ authorization.setMechanism(Mechanism.BASIC);
+ authManager.addAuth(authorization);
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -u 'user:passwd'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, AuthManager.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("canUpdateAuthManagerInThreadGroup", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, authManager };
+ assertFalse("When AuthManager contains this url, shouldn't add a AuthManager in ThreadGroup",
+ (boolean) method.invoke(p, objs));
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.fr/' -u 'user:passwd'");
+ objs = new Object[] { request, authManager };
+ assertTrue("The AuthManager doesn't contain this url , should add a AuthManager in ThreadGroup",
+ (boolean) method.invoke(p, objs));
+ }
+
+ @Test
+ public void testCreateCookieManager()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, IOException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ CookieManager cookieManager = new CookieManager();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -b 'name=Tom'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { CookieManager.class, Request.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("createCookieManager", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { cookieManager, request };
+ method.invoke(p, objs);
+ assertEquals("the domain of cookie should be set in cookieManager", "jmeter.apache.org",
+ cookieManager.get(0).getDomain());
+ assertEquals("the path of cookie should be set in cookieManager", "/", cookieManager.get(0).getPath());
+ assertEquals("the name of cookie should be set in cookieManager", "name", cookieManager.get(0).getName());
+ assertEquals("the password of cookie should be set in cookieManager", "Tom", cookieManager.get(0).getValue());
+ cookieManager = new CookieManager();
+ File file = tempFolder.newFile("test.txt");
+ String filepath = file.getAbsolutePath();
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -b '" + filepath + "'");
+ method = parseCurlCommandAction.getDeclaredMethod("createCookieManager", classes);
+ method.setAccessible(true);
+ objs = new Object[] { cookieManager, request };
+ method.invoke(p, objs);
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -b 'test1.txt'");
+ method = parseCurlCommandAction.getDeclaredMethod("createCookieManager", classes);
+ method.setAccessible(true);
+ objs = new Object[] { cookieManager, request };
+ try {
+ method.invoke(p, objs);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof IllegalArgumentException) {
+ assertTrue(cause.getMessage().contains("File test1.txt doesn't exist"));
+ }
+ }
+ }
+
+ @Test
+ public void testCreateCookieManagerHeader() throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException, NoSuchFieldException, SecurityException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ CookieManager cookieManager = new CookieManager();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser
+ .parse("curl 'http://jmeter.apache.org/' -H 'cookie: PHPSESSID=testphpsessid;a=b' --compressed");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { CookieManager.class, Request.class };
+ Field f = ParseCurlCommandAction.class.getDeclaredField("uploadCookiesCheckBox");
+ f.setAccessible(true);
+ JCheckBox uploadCookiesCheckBox = new JCheckBox(
+ JMeterUtils.getResString("curl_add_cookie_header_to_cookiemanager"), true);
+ f.set(p, uploadCookiesCheckBox);
+ Method method = parseCurlCommandAction.getDeclaredMethod("createCookieManager", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { cookieManager, request };
+ method.invoke(p, objs);
+ assertEquals("the domain of cookie should be set in cookieManager", "jmeter.apache.org",
+ cookieManager.get(0).getDomain());
+ assertEquals("the path of cookie should be set in cookieManager", "/", cookieManager.get(0).getPath());
+ assertEquals("the name of cookie should be set in cookieManager", "a", cookieManager.get(0).getName());
+ assertEquals("the password of cookie should be set in cookieManager", "b", cookieManager.get(0).getValue());
+ uploadCookiesCheckBox = new JCheckBox(JMeterUtils.getResString("curl_add_cookie_header_to_cookiemanager"),
+ false);
+ f.set(p, uploadCookiesCheckBox);
+ method = parseCurlCommandAction.getDeclaredMethod("createCookieManager", classes);
+ method.setAccessible(true);
+ cookieManager = new CookieManager();
+ objs = new Object[] { cookieManager, request };
+ method.invoke(p, objs);
+ assertTrue(
+ "When doesn't choose to upload cookies from header," + "the cookie shouldn't be set in cookieManager",
+ cookieManager.getCookies().size() == 0);
+ }
+
+ @Test
+ public void testDnsServer()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, IOException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ DNSCacheManager dnsCacheManager = new DNSCacheManager();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --dns-servers '0.0.0.0'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, DNSCacheManager.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("createDnsServer", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, dnsCacheManager };
+ method.invoke(p, objs);
+ assertEquals("the dns server should be set in DNSCacheManager", "0.0.0.0",
+ dnsCacheManager.getServers().get(0).getStringValue());
+ }
+
+ @Test
+ public void testCanAddDnsServerInHttpRequest()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, IOException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ DNSCacheManager dnsCacheManager = new DNSCacheManager();
+ dnsCacheManager.addServer("0.0.0.0");
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --dns-servers '0.0.0.0'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, DNSCacheManager.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("canAddDnsServerInHttpRequest", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, dnsCacheManager };
+ assertFalse("When the Dns servers are the same, shouldn't add the DnsCacheManager in Http Request",
+ (boolean) method.invoke(p, objs));
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --dns-servers '1.1.1.1'");
+ objs = new Object[] { request, dnsCacheManager };
+ assertTrue("When the Dns servers aren't the same, should add the DnsCacheManager in Http Request",
+ (boolean) method.invoke(p, objs));
+ }
+
+ @Test
+ public void testCreateDnsResolver()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, IOException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ DNSCacheManager dnsCacheManager = new DNSCacheManager();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ Request request = basicCurlParser
+ .parse("curl 'http://jmeter.apache.org/' --resolve 'moonagic.com:443:127.0.0.2'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, DNSCacheManager.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("createDnsResolver", classes);
+ method.setAccessible(true);
+ Object[] objs = new Object[] { request, dnsCacheManager };
+ method.invoke(p, objs);
+ assertEquals("the dns resolver should be set in DNSCacheManager", "StaticHost(moonagic.com, 127.0.0.2)",
+ dnsCacheManager.getHosts().get(0).getStringValue());
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --resolve 'moonagic.com:9090:127.0.0.2'");
+ method.setAccessible(true);
+ objs = new Object[] { request, dnsCacheManager };
+ method.invoke(p, objs);
+ assertEquals("the dns resolver should be set in DNSCacheManager", "StaticHost(moonagic.com, 127.0.0.2)",
+ dnsCacheManager.getHosts().get(0).getStringValue());
+ assertTrue("the dns resolver should be set in DNSCacheManager",
+ dnsCacheManager.getComment().contains("Custom DNS resolver doesn't support port"));
+ }
+
+ @Test
+ public void testCanAddDnsResolverInHttpRequest()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, IOException {
+ ParseCurlCommandAction p = new ParseCurlCommandAction();
+ BasicCurlParser basicCurlParser = new BasicCurlParser();
+ DNSCacheManager dnsCacheManager = new DNSCacheManager();
+ dnsCacheManager.addHost("moonagic.com", "127.0.0.2");
+ Request request = basicCurlParser
+ .parse("curl 'http://jmeter.apache.org/' --resolve 'moonagic.com:443:127.0.0.2'");
+ Class<ParseCurlCommandAction> parseCurlCommandAction = ParseCurlCommandAction.class;
+ Class[] classes = new Class[] { Request.class, DNSCacheManager.class };
+ Method method = parseCurlCommandAction.getDeclaredMethod("canAddDnsResolverInHttpRequest", classes);
+ method.setAccessible(true);
+ dnsCacheManager = new DNSCacheManager();
+ dnsCacheManager.addHost("moonagic.com", "127.0.0.2");
+ Object[] objs = new Object[] { request, dnsCacheManager };
+ method.invoke(p, objs);
+ assertFalse("When the Dns servers are the same, shouldn't add the DnsCacheManager in Http Request",
+ (boolean) method.invoke(p, objs));
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --resolve 'moonagic.com:9090:127.0.0.1'");
+ method.setAccessible(true);
+ objs = new Object[] { request, dnsCacheManager };
+ method.invoke(p, objs);
+ assertTrue("When the Dns servers aren't the same, should add the DnsCacheManager in Http Request",
+ (boolean) method.invoke(p, objs));
+ dnsCacheManager = new DNSCacheManager();
+ dnsCacheManager.addHost("moonagic.com", "127.0.0.1");
+ dnsCacheManager.addHost("moonagic.com", "127.0.0.2");
+ objs = new Object[] { request, dnsCacheManager };
+ method.invoke(p, objs);
+ assertTrue("When the Dns servers aren't the same, should add the DnsCacheManager in Http Request",
+ (boolean) method.invoke(p, objs));
+ request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' --resolve 'moonagic.com:9090:127.0.0.1'");
+ method.setAccessible(true);
+ objs = new Object[] { request, dnsCacheManager };
+ method.invoke(p, objs);
+ assertTrue("When the Dns servers aren't the same, should add the DnsCacheManager in Http Request",
+ (boolean) method.invoke(p, objs));
+ }
+}
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
index c9dd5dd..179d1ec 100644
--- a/xdocs/changes.xml
+++ b/xdocs/changes.xml
@@ -125,6 +125,8 @@ to view the last major behaviors with the version 5.1.1.
<li>Updated to httpclient/httpmime 4.5.8 (from 4.5.7)</li>
<li><bug>63396</bug>JSR223 Test Elements: Description of Parameters is misleading, same for Script</li>
<li><bug>63480</bug>XPathAssertion and XPathAssertion2: Improve test coverage for input coming from variable. Contributed by Ubik Load Pack (support at ubikloadpack.com)</li>
+ <li><bug>63452</bug>Tools / Import from cURL: Complete coverage of all command line options that are valid in JMeter use case. Contributed by Ubik Load Pack (support at ubikloadpack.com)</li>
+ <li><bug>63419</bug>CURL : Add ability to process a set of CURL commands. Contributed by Ubik Load Pack (support at ubikloadpack.com)</li>
</ul>
<ch_section>Non-functional changes</ch_section>
diff --git a/xdocs/images/screenshots/curl/choose_curl.png b/xdocs/images/screenshots/curl/choose_curl.png
new file mode 100644
index 0000000..6c23513
Binary files /dev/null and b/xdocs/images/screenshots/curl/choose_curl.png differ
diff --git a/xdocs/images/screenshots/curl/enter_command.png b/xdocs/images/screenshots/curl/enter_command.png
new file mode 100644
index 0000000..5e2d551
Binary files /dev/null and b/xdocs/images/screenshots/curl/enter_command.png differ
diff --git a/xdocs/images/screenshots/curl/enter_command_from_file.png b/xdocs/images/screenshots/curl/enter_command_from_file.png
new file mode 100644
index 0000000..e7dd4a8
Binary files /dev/null and b/xdocs/images/screenshots/curl/enter_command_from_file.png differ
diff --git a/xdocs/images/screenshots/curl/http_request_warning.png b/xdocs/images/screenshots/curl/http_request_warning.png
new file mode 100644
index 0000000..496cab2
Binary files /dev/null and b/xdocs/images/screenshots/curl/http_request_warning.png differ
diff --git a/xdocs/images/screenshots/curl/result.png b/xdocs/images/screenshots/curl/result.png
new file mode 100644
index 0000000..8c25f23
Binary files /dev/null and b/xdocs/images/screenshots/curl/result.png differ
diff --git a/xdocs/usermanual/curl.xml b/xdocs/usermanual/curl.xml
new file mode 100644
index 0000000..13d2c31
--- /dev/null
+++ b/xdocs/usermanual/curl.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<!DOCTYPE document
+[
+<!ENTITY sect-num '24'>
+<!ENTITY hellip "…" >
+]>
+<document id="$Id$" prev="glossary.html" next="history_future.html" >
+
+<properties>
+ <title>User's Manual: Curl</title>
+</properties>
+
+<body>
+
+<section name="§-num;. Curl" anchor="hints">
+<p>This method is to create http requests from curl command. If you want to know more about curl, please click the <a href="https://curl.haxx.se/">
+Curl document</a>.
+</p>
+<subsection name="§-num;.1 How to enter (a) command(s)" anchor="enter_command">
+<p>
+Create a Test Plan From a cURL Command
+</p>
+1. To create an import from a cURL, open the ‘Tools’ menu and click ‘Import from cURL’.
+<figure width="768" height="339" image="curl/choose_curl.png">Figure 1 - The menu where curl is located</figure>
+2.There are two ways to enter the curl command line. Firstly, we can enter it manually. Secondly, we can import a file containing the curl command line.
+This tool supports input of multiple curl command lines at the same time.
+<figure width="767" height="316" image="curl/enter_command.png">Figure 2.1 - Enter curl command in text panel</figure>
+<figure width="767" height="316" image="curl/enter_command_from_file.png">Figure 2.2 - Enter curl command from file</figure>
+3.Then, click ‘Create HTTP Request’ button and a new HTTP Sample will be added to the Test Plan.
+<figure width="767" height="316" image="curl/result.png">Figure 3 - result of Test Plan</figure>
+</subsection>
+
+<subsection name="§-num;.2 Curl options supported" anchor="curl_options">
+
+<p><b>-H, --header<header></b>:Extra header to use when getting a web page.</p>
+<p><b>-X, --request <command></b>:Specifies a custom request method to use when communicating with the HTTP server.</p>
+<p><b>--compressed</b>:Request a compressed response using one of the algorithms curl supports, and return the uncompressed document.</p>
+<p><b>-A, --user-agent <agent string ></b>:Specify the User-Agent string to send to the HTTP server.</p>
+<p><b>-b, --cookie <name=data></b>:Pass the data to the HTTP server as a cookie.</p>
+
+<b>Sends the specified data in a POST request to the HTTP server. If this option is used more than
+ once on the same command line, the data pieces specified will be merged together with a
+separating "&" character. Thus, using '-d name=daniel -d skill=lousy' would generate a POST
+ chunk that looks like 'name=daniel&skill=lousy'.</b>
+<ul><li>-d,--data <data> --data-ascii <data> :use @ to upload the file</li>
+<li> --data-binary <data> </li><li>--data-raw <data> : This posts data exactly as specified with no extra processing whatsoever.
+If you start the data with the character @, the rest should be a filename. </li>
+<li> --data-urlencode <data> :This posts data, similar to the other --data options with the exception that this performs
+ URL-encoding.</li>
+ <li> --data-raw <data> :This posts data similarly to --data but without the special interpretation
+of the @ character. </li>
+</ul>
+
+<b>This lets curl emulate a filled-in form in which a user has pressed the submit button.</b>
+<ul><li>-F, --form <name=content> :use @ to upload the file</li>
+<li>--form-string <name=content></li>
+</ul>
+<p><b>-u, --user <user:password ></b>:Specify user and password to use for server authentication.</p>
+<p><b>--basic,--digest</b>:Tells curl to use HTTP authentication.</p>
+
+<b>Tells curl to use the specified client certificate file when getting a file with HTTPS</b>
+<ul>
+<li>--cacert <CA certificate></li>
+<li>--capath <CA certificate directory></li>
+<li>--ciphers <list of ciphers> </li>
+<li>--cert-status</li>
+<li>--cert-type <type></li>
+</ul>
+<p><b>-G, --get</b>:put the post data in the url and use get to replace post.</p>
+<p><b>--no-keepalive</b>:Disables the use of keepalive messages on the TCP connection.</p>
+<p><b>-e, --referer <URL></b>:Sends the "Referer Page" information to the HTTP server.</p>
+<p><b>-L, --location</b>:If the server reports that the requested page has moved to a different location
+this option will make curl redo the request on the new place.</p>
+<p><b>-i, --include</b>:Include the HTTP-header in the output.</p>
+<p><b>--connect-timeout <seconds></b>:Maximum time in seconds that the connection to the server may take.</p>
+<p><b>--keepalive-time <seconds></b>:This option sets the time a connection needs to remain idle before sending keepalive probes and the time between individual keepalive probes.</p>
+<p><b>-m, --max-time <seconds></b>:Maximum time in seconds that you allow the whole operation to take.</p>
+<p><b>-x, --proxy <[protocol://] [user:password@] proxyhost[:port]> </b>:Use the specified HTTP proxy. If the port number is not specified, it is assumed at port 1080. </p>
+<p><b>-U, --proxy-user <user:password></b>:Specify user and password to use for proxy authentication. </p>
+<p><b>-k, --insecure</b>:This option explicitly allows curl to perform "insecure" SSL connections and transfers.</p>
+<p><b>--raw</b>:When used, it disables all internal HTTP decoding of content or transfer encodings and instead makes them passed on unaltered,raw.</p>
+<p><b>-I, --head</b>:Fetch the HTTP-header only. HTTP-servers feature the command HEAD which this uses to get nothing but the header of a document.</p>
+<p><b>--interface <name></b>:Perform an operation using a specified interface. You can enter interface name, IP address or host name.</p>
+<p><b>--proxy-ntlm/--proxy-negotiate</b>:Tells curl to use HTTP basic/ntlm/Digest authentication when communicating with the given proxy.</p>
+<p><b>--dns-servers <addresses></b>:Resolve host name over DOH.</p>
+<p><b>--resolve <host:port:address></b>:Provide a custom address for a specific host and port pair.</p>
+<p><b>--limit-rate <speed></b>:Specify the maximum transfer rate you want curl to use.</p>
+<p><b>--max-redirs <num></b>:Set maximum number of redirections which may be followed.</p>
+<p><b>--noproxy <no-proxy-list></b>:Comma-separated list of hosts which do not use a proxy, if one is specified.</p>
+</subsection>
+
+<subsection name="§-num;.3 Warning" anchor="warning">
+<p>
+When the command you entered is ignored or contains warning content, we will display warning in the comment section of Http Request.
+</p>
+<figure width="768" height="339" image="curl/http_request_warning.png">Figure 1 -Warning</figure>
+
+</subsection>
+<subsection name="§-num;.4 Examples" anchor="example">
+<p><b>Use cookie :</b>curl -X POST "https://xxx.com" -b 'username=Tom;password=123456'</p>
+<p><b>Use data :</b>curl -X POST "https://xxx.com" --data 'fname=a&lname=b'</p>
+<p><b>Use form :</b>curl -X POST "https://xxx.com" -F 'lname=a' -F 'fname=b' -F 'c=@C:\Test\test.txt' </p>
+<p><b>Use proxy :</b>curl 'http://jmeter.apache.org/' -x 'https://aa:bb@example.com:8042'</p>
+<p><b>Use autorization :</b>curl "https://xxx.com" -u 'user:passwd' --basic</p>
+<p><b>Use DNS :</b>curl "https://xxx.com" --dns-servers '0.0.0.0,1.1.1.1'</p>
+</subsection>
+</section>
+
+</body>
+</document>
diff --git a/xdocs/usermanual/glossary.xml b/xdocs/usermanual/glossary.xml
index 664c005..3c0947e 100644
--- a/xdocs/usermanual/glossary.xml
+++ b/xdocs/usermanual/glossary.xml
@@ -19,7 +19,7 @@
[
<!ENTITY sect-num '23'>
]>
-<document prev="hints_and_tips.html" next="history_future.html" id="$Id$">
+<document prev="hints_and_tips.html" next="curl.html" id="$Id$">
<properties>
<title>User's Manual: Glossary</title>
diff --git a/xdocs/usermanual/history_future.xml b/xdocs/usermanual/history_future.xml
index b1dae73..6c86f85 100644
--- a/xdocs/usermanual/history_future.xml
+++ b/xdocs/usermanual/history_future.xml
@@ -17,10 +17,10 @@
-->
<!DOCTYPE document
[
-<!ENTITY sect-num '24'>
+<!ENTITY sect-num '25'>
<!ENTITY hellip "…" >
]>
-<document id="$Id$" prev="glossary.html" >
+<document id="$Id$" prev="curl.html" >
<properties>
<title>User's Manual: History/Future</title>
diff --git a/xdocs/usermanual/index.xml b/xdocs/usermanual/index.xml
index f47e2ae..a4507d2 100644
--- a/xdocs/usermanual/index.xml
+++ b/xdocs/usermanual/index.xml
@@ -53,7 +53,8 @@
<li><a href="#regex">+</a>...<a href="regular_expressions.html">21. Regular Expressions</a></li>
<li><a href="#hints">+</a>...<a href="hints_and_tips.html">22. Hints and Tips</a></li>
<li><a href="#glossary">+</a>...<a href="glossary.html">23. Glossary</a></li>
- <li><a href="#history_future">+</a>...<a href="history_future.html">24. History / Future</a></li>
+ <li><a href="#curl">+</a>...<a href="curl.html">24. Curl</a></li>
+ <li><a href="#history_future">+</a>...<a href="history_future.html">25. History / Future</a></li>
</ul>
</subsection>
<subsection name="Detailed Section List" anchor="details">
@@ -205,7 +206,15 @@
<li><a name="regex"/><a href="regular_expressions.html">21. Regular Expressions</a></li>
<li><a name="hints"/><a href="hints_and_tips.html">22. Hints and Tips</a></li>
<li><a name="glossary"/><a href="glossary.html">23. Glossary</a></li>
- <li><a name="history_future"/><a href="history_future.html">24. History / Future</a></li>
+ <li><a name="curl"/><a href="curl.html">24. Curl</a>
+ <ul>
+ <li><a href="curl.html#enter_command">24.1 How to enter (a) command(s)</a></li>
+ <li><a href="curl.html#curl_options">24.2 Curl options supported</a></li>
+ <li><a href="curl.html#warning">24.3 Warning </a></li>
+ <li><a href="curl.html#example">24.4 Some Examples</a></li>
+ </ul>
+ </li>
+ <li><a name="history_future"/><a href="history_future.html">25. History / Future</a></li>
</ul>
</subsection>