aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2021-03-27 21:57:57 +0700
committerShulhan <ms@kilabit.info>2021-03-27 21:57:57 +0700
commiteaffbf8780e370ecec4e9bbc534694b8a815a86a (patch)
tree53d5f36d7059fdcf58824ab36cad103dc0d2fd08
parenta098c7d1641299e14ddfa88800922c128feff2d0 (diff)
downloadgorankusu-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.js18
-rw-r--r--example/example.go70
-rw-r--r--go.mod4
-rw-r--r--go.sum4
-rw-r--r--http_target.go2
-rw-r--r--run_response.go44
-rw-r--r--trunks.go131
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) {
diff --git a/go.mod b/go.mod
index acf15f8..b4c4688 100644
--- a/go.mod
+++ b/go.mod
@@ -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
diff --git a/go.sum b/go.sum
index 288305d..8e75b1c 100644
--- a/go.sum
+++ b/go.sum
@@ -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
+}
diff --git a/trunks.go b/trunks.go
index 919de36..5cb747b 100644
--- a/trunks.go
+++ b/trunks.go
@@ -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
}
//