aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
}
//