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   "&#x02026;" >
+]>
+<document id="$Id$" prev="glossary.html" next="history_future.html" >
+
+<properties>
+  <title>User's Manual: Curl</title>
+</properties>
+
+<body>
+
+<section name="&sect-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="&sect-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="&sect-num;.2 Curl options supported" anchor="curl_options">
+
+<p><b>-H, --header&lt;header&gt;</b>:Extra header to use when getting a web page.</p>
+<p><b>-X, --request &lt;command&gt;</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 &lt;agent string &gt;</b>:Specify the User-Agent string to send to the HTTP server.</p>
+<p><b>-b, --cookie &lt;name=data&gt;</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 "&amp;" character. Thus, using '-d name=daniel -d skill=lousy' would generate a POST
+ chunk that looks like 'name=daniel&amp;skill=lousy'.</b>
+<ul><li>-d,--data &lt;data&gt;  --data-ascii &lt;data&gt;  :use @ to upload the file</li>
+<li> --data-binary &lt;data&gt;  </li><li>--data-raw &lt;data&gt; : 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 &lt;data&gt; :This posts data, similar to the other --data options with the exception that this performs
+ URL-encoding.</li>
+ <li> --data-raw &lt;data&gt; :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 &lt;name=content&gt; :use @ to upload the file</li>
+<li>--form-string  &lt;name=content&gt;</li>
+</ul>
+<p><b>-u, --user &lt;user:password &gt;</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 &lt;CA certificate&gt;</li>
+<li>--capath  &lt;CA certificate directory&gt;</li>
+<li>--ciphers &lt;list of ciphers&gt; </li>
+<li>--cert-status</li>
+<li>--cert-type &lt;type&gt;</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 &lt;URL&gt;</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 &lt;seconds&gt;</b>:Maximum time in seconds that the connection to the server may take.</p>
+<p><b>--keepalive-time &lt;seconds&gt;</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  &lt;seconds&gt;</b>:Maximum time in seconds that you allow the whole operation to take.</p>
+<p><b>-x, --proxy &lt;[protocol://] [user:password@] proxyhost[:port]&gt; </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  &lt;user:password&gt;</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 &lt;name&gt;</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 &lt;addresses&gt;</b>:Resolve host name over DOH.</p>
+<p><b>--resolve &lt;host:port:address&gt;</b>:Provide a custom address for a specific host and port pair.</p>
+<p><b>--limit-rate &lt;speed&gt;</b>:Specify the maximum transfer rate you want curl to use.</p>
+<p><b>--max-redirs &lt;num&gt;</b>:Set maximum number of redirections which may be followed.</p>
+<p><b>--noproxy &lt;no-proxy-list&gt;</b>:Comma-separated list of hosts which do not use a proxy, if one is specified.</p>
+</subsection>
+
+<subsection name="&sect-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="&sect-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&amp;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   "&#x02026;" >
 ]>
-<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>