Build request data through RequestData struct instead of fasthttp directly

Refactor request generators to populate a script.RequestData intermediate struct, then apply it to fasthttp.Request in one step. This eliminates the round-trip conversion (fasthttp → RequestData → fasthttp) when scripts are enabled. Remove the URL field from RequestData and the now-unused fasthttp conversion functions from chain.go.
This commit is contained in:
2026-02-08 03:52:39 +04:00
parent 6dafc082ed
commit 6a713ef241
5 changed files with 87 additions and 143 deletions

View File

@@ -17,7 +17,7 @@ import (
type RequestGenerator func(*fasthttp.Request) error
type RequestGeneratorWithData func(*fasthttp.Request, any) error
type requestDataGenerator func(*script.RequestData, any) error
type valuesData struct {
Values map[string]string
@@ -59,13 +59,22 @@ func NewRequestGenerator(
hasScripts := scriptTransformer != nil && !scriptTransformer.IsEmpty()
host := requestURL.Host
scheme := requestURL.Scheme
reqData := &script.RequestData{
Headers: make(map[string][]string),
Params: make(map[string][]string),
Cookies: make(map[string][]string),
}
var (
data valuesData
path string
err error
)
return func(req *fasthttp.Request) error {
req.Header.SetHost(requestURL.Host)
resetRequestData(reqData)
data, err = valuesGenerator()
if err != nil {
@@ -76,44 +85,39 @@ func NewRequestGenerator(
if err != nil {
return err
}
req.SetRequestURI(path)
reqData.Path = path
if err = methodGenerator(req, data); err != nil {
if err = methodGenerator(reqData, data); err != nil {
return err
}
bodyTemplateFuncMapData.ClearFormDataContenType()
if err = bodyGenerator(req, data); err != nil {
if err = bodyGenerator(reqData, data); err != nil {
return err
}
if err = headersGenerator(req, data); err != nil {
if err = headersGenerator(reqData, data); err != nil {
return err
}
if bodyTemplateFuncMapData.GetFormDataContenType() != "" {
req.Header.Add("Content-Type", bodyTemplateFuncMapData.GetFormDataContenType())
reqData.Headers["Content-Type"] = append(reqData.Headers["Content-Type"], bodyTemplateFuncMapData.GetFormDataContenType())
}
if err = paramsGenerator(req, data); err != nil {
if err = paramsGenerator(reqData, data); err != nil {
return err
}
if err = cookiesGenerator(req, data); err != nil {
if err = cookiesGenerator(reqData, data); err != nil {
return err
}
if requestURL.Scheme == "https" {
req.URI().SetScheme("https")
}
// Apply script transformations if any
if hasScripts {
reqData := script.RequestDataFromFastHTTP(req)
if err = scriptTransformer.Transform(reqData); err != nil {
return err
}
script.ApplyToFastHTTP(reqData, req)
}
applyRequestDataToFastHTTP(reqData, req, host, scheme)
return nil
}, isPathGeneratorDynamic ||
isMethodGeneratorDynamic ||
@@ -124,50 +128,92 @@ func NewRequestGenerator(
hasScripts
}
func NewMethodGeneratorFunc(localRand *rand.Rand, methods []string, templateFunctions template.FuncMap) (RequestGeneratorWithData, bool) {
func resetRequestData(reqData *script.RequestData) {
reqData.Method = ""
reqData.Path = ""
reqData.Body = ""
clear(reqData.Headers)
clear(reqData.Params)
clear(reqData.Cookies)
}
func applyRequestDataToFastHTTP(reqData *script.RequestData, req *fasthttp.Request, host, scheme string) {
req.Header.SetHost(host)
req.SetRequestURI(reqData.Path)
req.Header.SetMethod(reqData.Method)
req.SetBody([]byte(reqData.Body))
for k, values := range reqData.Headers {
for _, v := range values {
req.Header.Add(k, v)
}
}
for k, values := range reqData.Params {
for _, v := range values {
req.URI().QueryArgs().Add(k, v)
}
}
if len(reqData.Cookies) > 0 {
cookieStrings := make([]string, 0, len(reqData.Cookies))
for k, values := range reqData.Cookies {
for _, v := range values {
cookieStrings = append(cookieStrings, k+"="+v)
}
}
req.Header.Add("Cookie", strings.Join(cookieStrings, "; "))
}
if scheme == "https" {
req.URI().SetScheme("https")
}
}
func NewMethodGeneratorFunc(localRand *rand.Rand, methods []string, templateFunctions template.FuncMap) (requestDataGenerator, bool) {
methodGenerator, isDynamic := buildStringSliceGenerator(localRand, methods, templateFunctions)
var (
method string
err error
)
return func(req *fasthttp.Request, data any) error {
return func(reqData *script.RequestData, data any) error {
method, err = methodGenerator()(data)
if err != nil {
return err
}
req.Header.SetMethod(method)
reqData.Method = method
return nil
}, isDynamic
}
func NewBodyGeneratorFunc(localRand *rand.Rand, bodies []string, templateFunctions template.FuncMap) (RequestGeneratorWithData, bool) {
func NewBodyGeneratorFunc(localRand *rand.Rand, bodies []string, templateFunctions template.FuncMap) (requestDataGenerator, bool) {
bodyGenerator, isDynamic := buildStringSliceGenerator(localRand, bodies, templateFunctions)
var (
body string
err error
)
return func(req *fasthttp.Request, data any) error {
return func(reqData *script.RequestData, data any) error {
body, err = bodyGenerator()(data)
if err != nil {
return err
}
req.SetBody([]byte(body))
reqData.Body = body
return nil
}, isDynamic
}
func NewParamsGeneratorFunc(localRand *rand.Rand, params types.Params, templateFunctions template.FuncMap) (RequestGeneratorWithData, bool) {
func NewParamsGeneratorFunc(localRand *rand.Rand, params types.Params, templateFunctions template.FuncMap) (requestDataGenerator, bool) {
generators, isDynamic := buildKeyValueGenerators(localRand, params, templateFunctions)
var (
key, value string
err error
)
return func(req *fasthttp.Request, data any) error {
return func(reqData *script.RequestData, data any) error {
for _, gen := range generators {
key, err = gen.Key(data)
if err != nil {
@@ -179,20 +225,20 @@ func NewParamsGeneratorFunc(localRand *rand.Rand, params types.Params, templateF
return err
}
req.URI().QueryArgs().Add(key, value)
reqData.Params[key] = append(reqData.Params[key], value)
}
return nil
}, isDynamic
}
func NewHeadersGeneratorFunc(localRand *rand.Rand, headers types.Headers, templateFunctions template.FuncMap) (RequestGeneratorWithData, bool) {
func NewHeadersGeneratorFunc(localRand *rand.Rand, headers types.Headers, templateFunctions template.FuncMap) (requestDataGenerator, bool) {
generators, isDynamic := buildKeyValueGenerators(localRand, headers, templateFunctions)
var (
key, value string
err error
)
return func(req *fasthttp.Request, data any) error {
return func(reqData *script.RequestData, data any) error {
for _, gen := range generators {
key, err = gen.Key(data)
if err != nil {
@@ -204,41 +250,33 @@ func NewHeadersGeneratorFunc(localRand *rand.Rand, headers types.Headers, templa
return err
}
req.Header.Add(key, value)
reqData.Headers[key] = append(reqData.Headers[key], value)
}
return nil
}, isDynamic
}
func NewCookiesGeneratorFunc(localRand *rand.Rand, cookies types.Cookies, templateFunctions template.FuncMap) (RequestGeneratorWithData, bool) {
func NewCookiesGeneratorFunc(localRand *rand.Rand, cookies types.Cookies, templateFunctions template.FuncMap) (requestDataGenerator, bool) {
generators, isDynamic := buildKeyValueGenerators(localRand, cookies, templateFunctions)
var (
key, value string
err error
)
if len(generators) > 0 {
return func(req *fasthttp.Request, data any) error {
cookieStrings := make([]string, 0, len(generators))
for _, gen := range generators {
key, err = gen.Key(data)
if err != nil {
return err
}
value, err = gen.Value()(data)
if err != nil {
return err
}
cookieStrings = append(cookieStrings, key+"="+value)
return func(reqData *script.RequestData, data any) error {
for _, gen := range generators {
key, err = gen.Key(data)
if err != nil {
return err
}
req.Header.Add("Cookie", strings.Join(cookieStrings, "; "))
return nil
}, isDynamic
}
return func(req *fasthttp.Request, data any) error {
value, err = gen.Value()(data)
if err != nil {
return err
}
reqData.Cookies[key] = append(reqData.Cookies[key], value)
}
return nil
}, isDynamic
}