Skip to content

Commit

Permalink
initial implementation with fasthttp
Browse files Browse the repository at this point in the history
  • Loading branch information
missedone committed Mar 8, 2016
1 parent 350e842 commit f7e2d04
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 34 deletions.
10 changes: 9 additions & 1 deletion src/github.com/eriklupander/gotling/httpaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type HttpAction struct {
Body string `yaml:"body"`
Accept string `yaml:"accept"`
Title string `yaml:"title"`
Client string `yaml:"client"`
ResponseHandler HttpResponseHandler `yaml:"response"`
}

Expand All @@ -42,7 +43,7 @@ func (h HttpAction) Execute(resultsChannel chan HttpReqResult, sessionMap map[st

type HttpResponseHandler struct {
Jsonpath string `yaml:"jsonpath"`
Xmlpath string `yaml:"xmlpath"`
Xmlpath string `yaml:"xmlpath"`
Variable string `yaml:"variable"`
Index string `yaml:"index"`
}
Expand Down Expand Up @@ -108,12 +109,19 @@ func NewHttpAction(a map[interface{}]interface{}) HttpAction {
accept = a["accept"].(string)
}

// default http client as Go net/http
httpclient := "std"
if a["client"] != nil && len(a["client"].(string)) > 0 {
httpclient = a["client"].(string)
}

httpAction := HttpAction{
a["method"].(string),
a["url"].(string),
getBody(a),
accept,
a["title"].(string),
httpclient,
responseHandler}

return httpAction
Expand Down
71 changes: 51 additions & 20 deletions src/github.com/eriklupander/gotling/httpreq.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,43 +24,77 @@ SOFTWARE.
package main

import (
"bytes"
"io/ioutil"
"log"
"math/rand"
"net/http"
"strings"
"time"
"gopkg.in/xmlpath.v2"

"github.com/NodePrime/jsonpath"
"bytes"
"github.com/valyala/fasthttp"
"gopkg.in/xmlpath.v2"
)

// Accepts a Httpaction and a one-way channel to write the results to.
func DoHttpRequest(httpAction HttpAction, resultsChannel chan HttpReqResult, sessionMap map[string]string) {
req := buildHttpRequest(httpAction, sessionMap)
client := &http.Client{}
start := time.Now()
resp, err := client.Do(req)
if err != nil {
//log.Printf("HTTP request failed")
} else {
if httpAction.Client == "fasthttp" {
// TODO ADD TLS CERT CONF SUPPORT
c := &fasthttp.Client{}

req := fasthttp.AcquireRequest()
req.Header.SetMethod(httpAction.Method)
req.Header.SetRequestURI(SubstParams(sessionMap, httpAction.Url))
req.Header.Set("Accept", httpAction.Accept)

resp := fasthttp.AcquireResponse()

defer fasthttp.ReleaseResponse(resp)
defer fasthttp.ReleaseRequest(req)

// TODO ADD TIMEOUT SUPPORT
start := time.Now()
err := c.Do(req, resp)
elapsed := time.Since(start)
responseBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
//log.Fatal(err)
log.Printf("Reading HTTP response failed: %s\n", err)
httpReqResult := buildHttpResult(0, resp.StatusCode, elapsed.Nanoseconds(), httpAction.Title)
log.Printf("Send HTTP request failed: %s\n", err)
httpReqResult := buildHttpResult(0, resp.Header.StatusCode(), elapsed.Nanoseconds(), httpAction.Title)

resultsChannel <- httpReqResult
} else {
defer resp.Body.Close()
// if action specifies response action, parse using regexp/jsonpath
responseBody := resp.Body()
processResult(httpAction, sessionMap, responseBody)

httpReqResult := buildHttpResult(len(responseBody), resp.StatusCode, elapsed.Nanoseconds(), httpAction.Title)
httpReqResult := buildHttpResult(len(responseBody), resp.Header.StatusCode(), elapsed.Nanoseconds(), httpAction.Title)

resultsChannel <- httpReqResult
}
} else {
req := buildHttpRequest(httpAction, sessionMap)
client := &http.Client{}
start := time.Now()
resp, err := client.Do(req)
if err != nil {
//log.Printf("HTTP request failed")
} else {
responseBody, err := ioutil.ReadAll(resp.Body)
elapsed := time.Since(start)
if err != nil {
//log.Fatal(err)
log.Printf("Reading HTTP response failed: %s\n", err)
httpReqResult := buildHttpResult(0, resp.StatusCode, elapsed.Nanoseconds(), httpAction.Title)

resultsChannel <- httpReqResult
} else {
defer resp.Body.Close()
// if action specifies response action, parse using regexp/jsonpath
processResult(httpAction, sessionMap, responseBody)

httpReqResult := buildHttpResult(len(responseBody), resp.StatusCode, elapsed.Nanoseconds(), httpAction.Title)

resultsChannel <- httpReqResult
}
}
}
}

Expand Down Expand Up @@ -130,7 +164,6 @@ func processResult(httpAction HttpAction, sessionMap map[string]string, response
passResultIntoSessionMap(resultsArray, httpAction, sessionMap)
}


if httpAction.ResponseHandler.Xmlpath != "" {
path := xmlpath.MustCompile(httpAction.ResponseHandler.Xmlpath)
r := bytes.NewReader(responseBody)
Expand Down Expand Up @@ -174,8 +207,6 @@ func trimChar(s string, r byte) string {
return s
}



func passResultIntoSessionMap(resultsArray []string, httpAction HttpAction, sessionMap map[string]string) {
resultCount := len(resultsArray)

Expand Down
26 changes: 13 additions & 13 deletions src/github.com/eriklupander/gotling/variableprocessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package main

import (
"regexp"
"strings"
"net/url"
"net/url"
"regexp"
"strings"
)

var re = regexp.MustCompile("\\$\\{([a-zA-Z0-9]{0,})\\}")

func SubstParams(sessionMap map[string]string, textData string) string {
if strings.ContainsAny(textData, "${") {
res := re.FindAllStringSubmatch(textData, -1)
for _, v := range res {
textData = strings.Replace(textData, "${" + v[1] + "}", url.QueryEscape(sessionMap[v[1]]), 1)
}
return textData
} else {
return textData
}
return textData
if strings.ContainsAny(textData, "${") {
res := re.FindAllStringSubmatch(textData, -1)
for _, v := range res {
textData = strings.Replace(textData, "${"+v[1]+"}", url.QueryEscape(sessionMap[v[1]]), 1)
}
return textData
} else {
return textData
}
}

0 comments on commit f7e2d04

Please sign in to comment.