diff options
| -rw-r--r-- | _www/index.js | 18 | ||||
| -rw-r--r-- | example/example.go | 70 | ||||
| -rw-r--r-- | go.mod | 4 | ||||
| -rw-r--r-- | go.sum | 4 | ||||
| -rw-r--r-- | http_target.go | 2 | ||||
| -rw-r--r-- | run_response.go | 44 | ||||
| -rw-r--r-- | trunks.go | 131 |
7 files changed, 159 insertions, 114 deletions
diff --git a/_www/index.js b/_www/index.js index 5512b14..a902ad1 100644 --- a/_www/index.js +++ b/_www/index.js @@ -184,7 +184,8 @@ function renderHttpTargets(target) { <h4>Parameters</h4> <div id="${http.ID}_params" class="params"></div> - <h4>Run response</h4> + <h4>Run output</h4> + <pre id="${http.ID}_request" class="response mono"></pre> <pre id="${http.ID}_response" class="response mono"></pre> <h4>Attack results</h4> @@ -397,19 +398,8 @@ async function run(targetID, httpTargetID) { return } - let elResponse = document.getElementById(httpTargetID + "_response") - let m = _requestMethods[req.HttpTarget.Method] - switch (m) { - case "GET": - case "POST": - case "PUT": - case "DELETE": - elResponse.innerHTML = JSON.stringify(res, null, 2) - break - default: - elResponse.innerHTML = atob(res.data) - break - } + document.getElementById(httpTargetID + "_request").innerHTML = atob(res.data.DumpRequest) + document.getElementById(httpTargetID + "_response").innerHTML = atob(res.data.DumpResponse) } async function runWebSocket(targetID, wstID) { diff --git a/example/example.go b/example/example.go index ba2dada..cbdb840 100644 --- a/example/example.go +++ b/example/example.go @@ -233,18 +233,43 @@ func (ex *Example) pathExamplePostForm(epr *libhttp.EndpointRequest) ([]byte, er return json.Marshal(&res) } -func (ex *Example) runExampleGet(req *trunks.RunRequest) ([]byte, error) { +func (ex *Example) runExampleGet(req *trunks.RunRequest) (res *trunks.RunResponse, err error) { if req.Target.HttpClient == nil { req.Target.HttpClient = libhttp.NewClient(req.Target.BaseUrl, nil, true) } - _, resbody, err := req.Target.HttpClient.Get( + + res = &trunks.RunResponse{} + + headers := req.HttpTarget.Headers.ToHttpHeader() + params := req.HttpTarget.Params.ToUrlValues() + + httpRequest, err := req.Target.HttpClient.GenerateHttpRequest( + req.HttpTarget.Method, req.HttpTarget.Path, - req.HttpTarget.Headers.ToHttpHeader(), - req.HttpTarget.Params.ToUrlValues()) + req.HttpTarget.RequestType, + headers, + params, + ) + if err != nil { + return nil, err + } + + err = res.SetHttpRequest(httpRequest) + if err != nil { + return nil, err + } + + httpResponse, _, err := req.Target.HttpClient.Do(httpRequest) + if err != nil { + return nil, err + } + + err = res.SetHttpResponse(httpResponse) if err != nil { return nil, err } - return resbody, nil + + return res, nil } func (ex *Example) preattackExampleGet(rr *trunks.RunRequest) { @@ -271,18 +296,43 @@ func (ex *Example) attackExampleGet(rr *trunks.RunRequest) vegeta.Targeter { } } -func (ex *Example) runExamplePostForm(req *trunks.RunRequest) ([]byte, error) { +func (ex *Example) runExamplePostForm(req *trunks.RunRequest) (res *trunks.RunResponse, err error) { if req.Target.HttpClient == nil { req.Target.HttpClient = libhttp.NewClient(req.Target.BaseUrl, nil, true) } - _, resbody, err := req.Target.HttpClient.PostForm( + + res = &trunks.RunResponse{} + + headers := req.HttpTarget.Headers.ToHttpHeader() + params := req.HttpTarget.Params.ToUrlValues() + + httpRequest, err := req.Target.HttpClient.GenerateHttpRequest( + req.HttpTarget.Method, req.HttpTarget.Path, - req.HttpTarget.Headers.ToHttpHeader(), - req.HttpTarget.Params.ToUrlValues()) + req.HttpTarget.RequestType, + headers, + params, + ) + if err != nil { + return nil, err + } + + err = res.SetHttpRequest(httpRequest) + if err != nil { + return nil, err + } + + httpResponse, _, err := req.Target.HttpClient.Do(httpRequest) + if err != nil { + return nil, err + } + + err = res.SetHttpResponse(httpResponse) if err != nil { return nil, err } - return resbody, nil + + return res, nil } func (ex *Example) preattackExamplePostForm(rr *trunks.RunRequest) { @@ -6,8 +6,10 @@ require ( github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654 // indirect github.com/influxdata/tdigest v0.0.1 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/shuLhan/share v0.24.1-0.20210321092144-d4f1f279b631 + github.com/shuLhan/share v0.24.1-0.20210327143930-4cdd6b01c14b github.com/tsenart/vegeta/v12 v12.8.4 golang.org/x/net v0.0.0-20210315170653-34ac3e1c2000 // indirect golang.org/x/text v0.3.5 // indirect ) + +//replace github.com/shuLhan/share => ../share @@ -26,8 +26,8 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/miekg/dns v1.1.17/go.mod h1:WgzbA6oji13JREwiNsRDNfl7jYdPnmz+VEuLrA+/48M= -github.com/shuLhan/share v0.24.1-0.20210321092144-d4f1f279b631 h1:/aIE4Q48KUHC4NufZhx9fNyCdPJxB5nX53jlXbKQGZc= -github.com/shuLhan/share v0.24.1-0.20210321092144-d4f1f279b631/go.mod h1:c6xnA1EctNz2KGVlekfydyXoUjpTPjyUHUIyWSELN/c= +github.com/shuLhan/share v0.24.1-0.20210327143930-4cdd6b01c14b h1:NykUKIze94kWmnUGhxcDvUewYHqiSUVx+dYM9AVXA5U= +github.com/shuLhan/share v0.24.1-0.20210327143930-4cdd6b01c14b/go.mod h1:c6xnA1EctNz2KGVlekfydyXoUjpTPjyUHUIyWSELN/c= github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 h1:7z3LSn867ex6VSaahyKadf4WtSsJIgne6A1WLOAGM8A= github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= github.com/tsenart/go-tsz v0.0.0-20180814232043-cdeb9e1e981e/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo= diff --git a/http_target.go b/http_target.go index f21df13..79057bb 100644 --- a/http_target.go +++ b/http_target.go @@ -19,7 +19,7 @@ import ( // HttpRunHandler define the function type that will be called when client // send request to run the HTTP target. // -type HttpRunHandler func(rr *RunRequest) ([]byte, error) +type HttpRunHandler func(rr *RunRequest) (runres *RunResponse, err error) // // HttpAttackHandler define the function type that will be called when client diff --git a/run_response.go b/run_response.go new file mode 100644 index 0000000..de12105 --- /dev/null +++ b/run_response.go @@ -0,0 +1,44 @@ +// Copyright 2021, Shulhan <ms@kilabit.info>. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package trunks + +import ( + "fmt" + "net/http" + "net/http/httputil" +) + +// +// RunResponse contains the raw request and response when running HTTP or +// WebSocket target. +// +type RunResponse struct { + DumpRequest []byte + DumpResponse []byte +} + +// +// SetHttpResponse dump the HTTP request including body into the DumpRequest +// field. +// +func (rres *RunResponse) SetHttpRequest(req *http.Request) (err error) { + rres.DumpRequest, err = httputil.DumpRequest(req, true) + if err != nil { + return fmt.Errorf("SetHttpRequest: %w", err) + } + return nil +} + +// +// SetHttpResponse dump the HTTP response including body into the DumpResponse +// field. +// +func (rres *RunResponse) SetHttpResponse(res *http.Response) (err error) { + rres.DumpResponse, err = httputil.DumpResponse(res, true) + if err != nil { + return fmt.Errorf("SetHttpResponse: %w", err) + } + return nil +} @@ -8,7 +8,6 @@ import ( "encoding/json" "fmt" "net/http" - "net/http/httputil" "os" "sort" "strings" @@ -405,15 +404,25 @@ func (trunks *Trunks) apiTargetRunHttp(epr *libhttp.EndpointRequest) ([]byte, er return nil, errInvalidHttpTarget(req.HttpTarget.ID) } - if req.HttpTarget.Run != nil { + var res *RunResponse + + if req.HttpTarget.Run == nil { + req.Target.BaseUrl = origTarget.BaseUrl + req.Target.Name = origTarget.Name + res, err = trunks.runHttpTarget(req) + } else { req.mergeHttpTarget(trunks.Env, origTarget, origHttpTarget) - return req.HttpTarget.Run(req) + res, err = req.HttpTarget.Run(req) + } + if err != nil { + return nil, errInternal(err) } - req.Target.BaseUrl = origTarget.BaseUrl - req.Target.Name = origTarget.Name + epres := libhttp.EndpointResponse{} + epres.Code = http.StatusOK + epres.Data = res - return trunks.runHttpTarget(req) + return json.Marshal(&epres) } func (trunks *Trunks) apiTargetRunWebSocket(epr *libhttp.EndpointRequest) ([]byte, error) { @@ -503,99 +512,49 @@ func (trunks *Trunks) getTargetByResultFilename(name string) (t *Target, ht *Htt return t, ht } -func (trunks *Trunks) runHttpTarget(rr *RunRequest) (resbody []byte, err error) { +func (trunks *Trunks) runHttpTarget(rr *RunRequest) (res *RunResponse, err error) { var ( - httpRes *http.Response - res = libhttp.EndpointResponse{} + logp = "runHttpTarget" httpc = libhttp.NewClient(rr.Target.BaseUrl, nil, true) headers = rr.HttpTarget.Headers.ToHttpHeader() - params = rr.HttpTarget.Params.ToUrlValues() + params interface{} ) - switch rr.HttpTarget.Method { - case libhttp.RequestMethodGet: - httpRes, resbody, err = httpc.Get(rr.HttpTarget.Path, headers, params) - - case libhttp.RequestMethodConnect, - libhttp.RequestMethodDelete, - libhttp.RequestMethodHead, - libhttp.RequestMethodOptions, - libhttp.RequestMethodPatch, - libhttp.RequestMethodTrace: - - httpReq, err := http.NewRequest(rr.HttpTarget.Method.String(), - fmt.Sprintf("%s%s", rr.Target.BaseUrl, rr.HttpTarget.Path), - nil) - if err != nil { - mlog.Errf("runHttpTarget: %s %s: %s\n", - rr.HttpTarget.Method.String(), - rr.HttpTarget.Path, err) - return nil, errInternal(err) - } - - httpRes, err = httpc.Do(httpReq) - if err != nil { - mlog.Errf("runHttpTarget: %s %s: %s\n", - rr.HttpTarget.Method.String(), - rr.HttpTarget.Path, err) - return nil, errInternal(err) - } - - dumpres, err := httputil.DumpResponse(httpRes, true) - if err != nil { - mlog.Errf("runHttpTarget: %s %s: %s\n", - rr.HttpTarget.Method.String(), - rr.HttpTarget.Path, err) - return nil, errInternal(err) - } - - res.Code = http.StatusOK - res.Data = dumpres - return json.Marshal(res) - - case libhttp.RequestMethodPost: - switch rr.HttpTarget.RequestType { - case libhttp.RequestTypeNone, - libhttp.RequestTypeQuery: - httpRes, resbody, err = httpc.Post( - rr.HttpTarget.Path, headers, params) - - case libhttp.RequestTypeForm: - httpRes, resbody, err = httpc.PostForm( - rr.HttpTarget.Path, headers, params) + if rr.HttpTarget.RequestType == libhttp.RequestTypeJSON { + params = rr.HttpTarget.Params + } else { + params = rr.HttpTarget.Params.ToUrlValues() + } - case libhttp.RequestTypeMultipartForm: - httpRes, resbody, err = httpc.PostFormData( - rr.HttpTarget.Path, headers, - rr.HttpTarget.Params.ToMultipartFormData()) + res = &RunResponse{} - case libhttp.RequestTypeJSON: - httpRes, resbody, err = httpc.PostJSON( - rr.HttpTarget.Path, headers, - rr.HttpTarget.Params) - } + httpRequest, err := httpc.GenerateHttpRequest( + rr.HttpTarget.Method, + rr.HttpTarget.Path, + rr.HttpTarget.RequestType, + headers, + params, + ) + if err != nil { + return nil, fmt.Errorf("%s: %w", logp, err) + } - case libhttp.RequestMethodPut: - if rr.HttpTarget.RequestType == libhttp.RequestTypeJSON { - httpRes, resbody, err = httpc.PutJSON( - rr.HttpTarget.Path, headers, - rr.HttpTarget.Params) - } else { - httpRes, resbody, err = httpc.Put( - rr.HttpTarget.Path, headers, nil) - } + err = res.SetHttpRequest(httpRequest) + if err != nil { + return nil, fmt.Errorf("%s: %w", logp, err) } + + httpResponse, _, err := httpc.Do(httpRequest) if err != nil { - return nil, errInternal(err) + return nil, fmt.Errorf("%s: %w", logp, err) } - if httpRes.StatusCode != http.StatusOK { - res.Code = httpRes.StatusCode - res.Message = httpRes.Status - res.Data = resbody - return json.Marshal(res) + + err = res.SetHttpResponse(httpResponse) + if err != nil { + return nil, fmt.Errorf("%s: %w", logp, err) } - return resbody, err + return res, nil } // |
