diff --git a/README.md b/README.md index 6dd6e9ee..dcc7fd4f 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,7 @@ The features you can use by config file; - Scenario creation - Custom load type creation - Payload from a file +- Multipart/form-data payload - Extra connection configuration, like *keep-alive* enable/disable logic - HTTP2 support @@ -253,6 +254,68 @@ There is an example config file at [config_examples/config.json](/config_example If you need a long payload, we suggest using this parameter instead of `payload`. + - `payload_multipart` *optional* + + Use this for `multipart/form-data` Content-Type. + + Accepts list of `form-field` object structured as below; + ```json + { + "name": [field-name], + "value": [field-value|file-path|url], + "type": , // Default "text" + "src": // Default "local" + } + ``` + + **Example:** Sending form name-value pairs; + ```json + "payload_multipart": [ + { + "name": "[field-name]", + "value": "[field-value]" + } + ] + ``` + + **Example:** Sending form name-value pairs and a local file; + ```json + "payload_multipart": [ + { + "name": "[field-name]", + "value": "[field-value]", + }, + { + "name": "[field-name]", + "value": "./test.png", + "type": "file" + } + ] + ``` + + **Example:** Sending form name-value pairs and a local file and a remote file; + ```json + "payload_multipart": [ + { + "name": "[field-name]", + "value": "[field-value]", + }, + { + "name": "[field-name]", + "value": "./test.png", + "type": "file" + }, + { + "name": "[field-name]", + "value": "http://test.com/test.png", + "type": "file", + "src": "remote" + } + ] + ``` + + *Note:* Ddosify adds `Content-Type: multipart/form-data; boundary=[generated-boundary-value]` header to the request when using `payload_multipart`. + - `timeout` *optional* This is the equivalent of the `-T` flag. diff --git a/config/json.go b/config/json.go index 195f64c9..a85681d8 100644 --- a/config/json.go +++ b/config/json.go @@ -240,52 +240,47 @@ func prepareMultipartPayload(parts []multipartFormData) (body string, contentTyp var err error if strings.EqualFold(part.Type, "file") { - - if part.Src == "" || strings.EqualFold(part.Src, "local") { - file, err := os.Open(part.Value) - defer file.Close() + if strings.EqualFold(part.Src, "remote") { + response, err := http.Get(part.Value) if err != nil { return "", "", err } + defer response.Body.Close() - formPart, err := writer.CreateFormFile(part.Name, filepath.Base(file.Name())) + u, _ := url.Parse(part.Value) + formPart, err := writer.CreateFormFile(part.Name, path.Base(u.Path)) if err != nil { return "", "", err } - _, err = io.Copy(formPart, file) + _, err = io.Copy(formPart, response.Body) if err != nil { return "", "", err } - } else if strings.EqualFold(part.Src, "remote") { - response, err := http.Get(part.Value) + } else { + file, err := os.Open(part.Value) + defer file.Close() if err != nil { return "", "", err } - defer response.Body.Close() - u, _ := url.Parse(part.Value) - formPart, err := writer.CreateFormFile(part.Name, path.Base(u.Path)) + formPart, err := writer.CreateFormFile(part.Name, filepath.Base(file.Name())) if err != nil { return "", "", err } - _, err = io.Copy(formPart, response.Body) + _, err = io.Copy(formPart, file) if err != nil { return "", "", err } - } else { - return "", "", fmt.Errorf("invalid multipart/form-data src: %v", part.Src) } - } else if strings.EqualFold(part.Type, "text") { + } else { // If we have to specify Content-Type in Content-Disposition, we should use writer.CreatePart directly. err = writer.WriteField(part.Name, part.Value) if err != nil { return "", "", err } - } else { - return "", "", fmt.Errorf("invalid multipart/form-data field type:%s", part.Type) } } diff --git a/config_examples/config.json b/config_examples/config.json index 7237c489..c4949c49 100644 --- a/config_examples/config.json +++ b/config_examples/config.json @@ -41,6 +41,29 @@ "payload_file": "config_examples/payload.txt", "timeout": 2, "sleep": "1000" + }, + { + "id": 3, + "url": "https://test_site1.com/endpoint_3", + "method": "POST", + "payload_multipart": [ + { + "name": "[field-name]", + "value": "[field-value]" + }, + { + "name": "[field-name]", + "value": "./test.png", + "type": "file" + }, + { + "name": "[field-name]", + "value": "http://test.com/test.png", + "type": "file", + "src": "remote" + } + ], + "timeout": 2 } ] } \ No newline at end of file