diff options
| -rw-r--r-- | example.go | 14 | ||||
| -rw-r--r-- | go.mod | 2 | ||||
| -rw-r--r-- | go.sum | 4 | ||||
| -rw-r--r-- | http_attack_handler.go | 13 | ||||
| -rw-r--r-- | http_params_converter.go | 4 | ||||
| -rw-r--r-- | key_form_input.go | 80 | ||||
| -rw-r--r-- | testdata/target_http_run_formkindfile_test.txt | 40 |
7 files changed, 89 insertions, 68 deletions
@@ -554,19 +554,7 @@ func (ex *Example) pathExampleRawbodyJSON(epr *libhttp.EndpointRequest) (resbody } func (ex *Example) pathExampleUpload(epr *libhttp.EndpointRequest) (resb []byte, err error) { - var logp = `pathExampleUpload` - - var res = libhttp.EndpointResponse{} - - res.Code = http.StatusOK - res.Data = epr.HTTPRequest.MultipartForm.Value - - resb, err = json.MarshalIndent(res, ``, ` `) - if err != nil { - return nil, fmt.Errorf(`%s: %w`, logp, err) - } - - return resb, nil + return epr.RequestBody, nil } func (ex *Example) handleWSExampleGet(_ context.Context, req *websocket.Request) (res websocket.Response) { @@ -7,7 +7,7 @@ go 1.21 require ( git.sr.ht/~shulhan/ciigo v0.12.0 - git.sr.ht/~shulhan/pakakeh.go v0.54.0 + git.sr.ht/~shulhan/pakakeh.go v0.54.1-0.20240424075702-072a5866613a github.com/tsenart/vegeta/v12 v12.11.1 golang.org/x/tools v0.20.0 ) @@ -2,8 +2,8 @@ git.sr.ht/~shulhan/asciidoctor-go v0.5.2 h1:tjG/NQJ1om2F70L7DwOvmr+n1kfgk9xhIBX+ git.sr.ht/~shulhan/asciidoctor-go v0.5.2/go.mod h1:fHXUiw7IbOOMyoHHvnd351Jini/MNZgutiFTtsCQ+Yk= git.sr.ht/~shulhan/ciigo v0.12.0 h1:LSjFcA4nwJvPU2Xn/Mlz9520XSSvt6oyUtN1ARu0m6o= git.sr.ht/~shulhan/ciigo v0.12.0/go.mod h1:v5xCYhQK4JRJ7ZuW2J7lUknDLwzaNknZCw3jqaMDSYA= -git.sr.ht/~shulhan/pakakeh.go v0.54.0 h1:pwTQiJSyE5xTaWNR0FnWsszJ+0Z5hB2ufNLXcy8z0y8= -git.sr.ht/~shulhan/pakakeh.go v0.54.0/go.mod h1:ys7WNtXm03x0M59oqrqBjXnc+wRCX8JBXyE/W8+KVbw= +git.sr.ht/~shulhan/pakakeh.go v0.54.1-0.20240424075702-072a5866613a h1:0UUJkeUzFGYdnoIpGi4n+ZGZG4MnQfg8YBZ1jQuhBDY= +git.sr.ht/~shulhan/pakakeh.go v0.54.1-0.20240424075702-072a5866613a/go.mod h1:hJHTZtPS9bOKMNtLljEdJZKHj3eOAXe7fuHcfI6vceY= github.com/bmizerany/perks v0.0.0-20230307044200-03f9df79da1e h1:mWOqoK5jV13ChKf/aF3plwQ96laasTJgZi4f1aSOu+M= github.com/bmizerany/perks v0.0.0-20230307044200-03f9df79da1e/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= diff --git a/http_attack_handler.go b/http_attack_handler.go index fc5656b..c39e242 100644 --- a/http_attack_handler.go +++ b/http_attack_handler.go @@ -6,6 +6,7 @@ package gorankusu import ( "encoding/json" "fmt" + "mime/multipart" libhttp "git.sr.ht/~shulhan/pakakeh.go/lib/http" vegeta "github.com/tsenart/vegeta/v12/lib" @@ -58,15 +59,17 @@ func DefaultHTTPAttack() HTTPAttackHandler { case libhttp.RequestTypeMultipartForm: var ( - params map[string][]byte + params *multipart.Form body string ) - params = rr.HTTPTarget.Params.ToMultipartFormData() - contentType, body, err = libhttp.GenerateFormData(params) + params, err = rr.HTTPTarget.Params.ToMultipartFormData() if err == nil { - vegetaTarget.Body = []byte(body) - vegetaTarget.Header.Set(libhttp.HeaderContentType, contentType) + contentType, body, err = libhttp.GenerateFormData(params) + if err == nil { + vegetaTarget.Body = []byte(body) + vegetaTarget.Header.Set(libhttp.HeaderContentType, contentType) + } } } } diff --git a/http_params_converter.go b/http_params_converter.go index 9a4ef91..b885f64 100644 --- a/http_params_converter.go +++ b/http_params_converter.go @@ -18,10 +18,10 @@ func DefaultParamsConverter() HTTPParamsConverter { case libhttp.RequestTypeJSON: params = target.Params.ToJSONObject() case libhttp.RequestTypeMultipartForm: - params = target.Params.ToMultipartFormData() + params, err = target.Params.ToMultipartFormData() default: params = target.Params.ToURLValues() } - return params, nil + return params, err } } diff --git a/key_form_input.go b/key_form_input.go index 61cbe41..7a0c571 100644 --- a/key_form_input.go +++ b/key_form_input.go @@ -4,11 +4,14 @@ package gorankusu import ( + "fmt" + "mime/multipart" "net/http" "net/url" "strconv" "strings" + libhttp "git.sr.ht/~shulhan/pakakeh.go/lib/http" "git.sr.ht/~shulhan/pakakeh.go/lib/math/big" ) @@ -69,38 +72,67 @@ func (kfi KeyFormInput) ToJSONObject() (data map[string]interface{}) { return data } -// ToMultipartFormData convert the KeyFormInput into map of string and raw -// bytes. -func (kfi KeyFormInput) ToMultipartFormData() (data map[string][]byte) { - data = make(map[string][]byte, len(kfi)) +// ToMultipartFormData convert the KeyFormInput into [*multipart.Form]. +func (kfi KeyFormInput) ToMultipartFormData() (data *multipart.Form, err error) { + var logp = `ToMultipartFormData` + + data = &multipart.Form{ + Value: map[string][]string{}, + File: map[string][]*multipart.FileHeader{}, + } if len(kfi) == 0 { - return data + return data, nil } - for k, fi := range kfi { - if fi.Kind == FormInputKindFile { - var name string - if len(fi.Filename) != 0 { - name = fi.FormDataName(FormDataFilename) - data[name] = []byte(fi.Filename) - } - if len(fi.Filetype) != 0 { - name = fi.FormDataName(FormDataFiletype) - data[name] = []byte(fi.Filetype) - } - name = fi.FormDataName(FormDataFilesize) - data[name] = []byte(strconv.FormatInt(fi.Filesize, 10)) + var ( + k string + fi FormInput + listValue []string + ) + for k, fi = range kfi { + if fi.Kind != FormInputKindFile { + listValue = data.Value[k] + listValue = append(listValue, fi.Value) + data.Value[k] = listValue + continue + } + + // Process form with type File. - name = fi.FormDataName(FormDataFilemodms) - data[name] = []byte(strconv.FormatInt(fi.Filemodms, 10)) + var ( + filename string + fieldname string + ) - name = fi.FormDataName(FormDataFilecontent) - data[name] = []byte(fi.Value) + if len(fi.Filename) != 0 { + filename = fi.Filename } else { - data[k] = []byte(fi.Value) + filename = k } + + if len(fi.Filetype) != 0 { + fieldname = fi.FormDataName(FormDataFiletype) + data.Value[fieldname] = []string{fi.Filetype} + } + + fieldname = fi.FormDataName(FormDataFilesize) + data.Value[fieldname] = []string{strconv.FormatInt(fi.Filesize, 10)} + + fieldname = fi.FormDataName(FormDataFilemodms) + data.Value[fieldname] = []string{strconv.FormatInt(fi.Filemodms, 10)} + + var fh *multipart.FileHeader + + fh, err = libhttp.CreateMultipartFileHeader(filename, []byte(fi.Value)) + if err != nil { + return nil, fmt.Errorf(`%s: %w`, logp, err) + } + + var listFH = data.File[k] + listFH = append(listFH, fh) + data.File[k] = listFH } - return data + return data, nil } // ToURLValues convert the KeyFormInput to the standard url.Values. diff --git a/testdata/target_http_run_formkindfile_test.txt b/testdata/target_http_run_formkindfile_test.txt index 9dbf1ba..8932b1c 100644 --- a/testdata/target_http_run_formkindfile_test.txt +++ b/testdata/target_http_run_formkindfile_test.txt @@ -24,26 +24,24 @@ Test data for testing running HTTP with form kind is file (uploading file). <<< valid:RunResponse.DumpResponse HTTP/1.1 200 OK -Content-Length: 256 +Content-Length: 637 Content-Type: application/json -{ - "data": { - "filecontent": [ - "Q29udGVudCBvZiBmaWxlIHVwbG9hZA==" - ], - "filemodms": [ - "0" - ], - "filesize": [ - "22" - ], - "filetype": [ - "text/plain" - ], - "name": [ - "test.txt" - ] - }, - "code": 200 -} +--6f72616e6b7573756f72616e6b7573756f72616e6b7573756f72616e6b75 +Content-Disposition: form-data; name="file"; filename="test.txt" +Content-Type: application/octet-stream + +Q29udGVudCBvZiBmaWxlIHVwbG9hZA== +--6f72616e6b7573756f72616e6b7573756f72616e6b7573756f72616e6b75 +Content-Disposition: form-data; name="filemodms" + +0 +--6f72616e6b7573756f72616e6b7573756f72616e6b7573756f72616e6b75 +Content-Disposition: form-data; name="filesize" + +22 +--6f72616e6b7573756f72616e6b7573756f72616e6b7573756f72616e6b75 +Content-Disposition: form-data; name="filetype" + +text/plain +--6f72616e6b7573756f72616e6b7573756f72616e6b7573756f72616e6b75-- |
