diff options
| author | Shulhan <ms@kilabit.info> | 2021-03-27 21:57:57 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2021-03-27 21:57:57 +0700 |
| commit | eaffbf8780e370ecec4e9bbc534694b8a815a86a (patch) | |
| tree | 53d5f36d7059fdcf58824ab36cad103dc0d2fd08 | |
| parent | a098c7d1641299e14ddfa88800922c128feff2d0 (diff) | |
| download | gorankusu-eaffbf8780e370ecec4e9bbc534694b8a815a86a.tar.xz | |
all: change the Run result to return dump of HTTP request and response
Previously, we display the actual response of the HTTP target only
on the user interface.
This changes make the Run function to display the actual HTTP request and
response that being send and received on HTTP target.
| -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 } // |
