From 46639cae1836bb5b81481e6dff3d4507cf43d406 Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Sun, 23 Jul 2023 13:49:56 +0800 Subject: [PATCH] fix: build url, handle request params --- hrp/parser.go | 20 +++++++++---- hrp/parser_test.go | 59 ++++++++++++++++++++++++--------------- hrp/step_request.go | 68 ++++++++------------------------------------- 3 files changed, 62 insertions(+), 85 deletions(-) diff --git a/hrp/parser.go b/hrp/parser.go index 7e54edc5..211101fb 100644 --- a/hrp/parser.go +++ b/hrp/parser.go @@ -28,24 +28,34 @@ type Parser struct { plugin funplugin.IPlugin // plugin is used to call functions } -func buildURL(baseURL, stepURL string) (fullUrl string) { +func buildURL(baseURL, stepURL string, queryParams url.Values) (fullUrl *url.URL) { uStep, err := url.Parse(stepURL) if err != nil { log.Error().Str("stepURL", stepURL).Err(err).Msg("[buildURL] parse url failed") - return stepURL + return nil } defer func() { + // append query params + if paramStr := queryParams.Encode(); paramStr != "" { + if uStep.RawQuery == "" { + uStep.RawQuery = paramStr + } else { + uStep.RawQuery = uStep.RawQuery + "&" + paramStr + } + } + // ensure path suffix '/' exists if uStep.RawQuery == "" { uStep.Path = strings.TrimRight(uStep.Path, "/") + "/" } - fullUrl = uStep.String() + + fullUrl = uStep }() // step url is absolute url if uStep.Host != "" { - return + return uStep } // step url is relative, based on base url @@ -59,7 +69,7 @@ func buildURL(baseURL, stepURL string) (fullUrl string) { uStep.Scheme = uConfig.Scheme uStep.Host = uConfig.Host uStep.Path = path.Join(uConfig.Path, uStep.Path) - return + return uStep } func (p *Parser) ParseHeaders(rawHeaders map[string]string, variablesMapping map[string]interface{}) (map[string]string, error) { diff --git a/hrp/parser_test.go b/hrp/parser_test.go index 9f9e7e04..b007c5e6 100644 --- a/hrp/parser_test.go +++ b/hrp/parser_test.go @@ -1,6 +1,7 @@ package hrp import ( + "net/url" "sort" "testing" "time" @@ -9,60 +10,72 @@ import ( ) func TestBuildURL(t *testing.T) { - var url string + var preparedURL *url.URL - url = buildURL("https://postman-echo.com", "/get") - if !assert.Equal(t, url, "https://postman-echo.com/get/") { + preparedURL = buildURL("https://postman-echo.com", "/get", nil) + if !assert.Equal(t, preparedURL.String(), "https://postman-echo.com/get/") { t.Fatal() } - url = buildURL("https://postman-echo.com", "get") - if !assert.Equal(t, url, "https://postman-echo.com/get/") { + preparedURL = buildURL("https://postman-echo.com", "get", nil) + if !assert.Equal(t, preparedURL.String(), "https://postman-echo.com/get/") { t.Fatal() } - url = buildURL("https://postman-echo.com/", "/get") - if !assert.Equal(t, url, "https://postman-echo.com/get/") { + preparedURL = buildURL("https://postman-echo.com/", "/get", nil) + if !assert.Equal(t, preparedURL.String(), "https://postman-echo.com/get/") { t.Fatal() } - url = buildURL("https://postman-echo.com/abc/", "/get?a=1&b=2") - if !assert.Equal(t, url, "https://postman-echo.com/abc/get?a=1&b=2") { + preparedURL = buildURL("https://postman-echo.com/abc/", "/get?a=1&b=2", nil) + if !assert.Equal(t, preparedURL.String(), "https://postman-echo.com/abc/get?a=1&b=2") { t.Fatal() } - url = buildURL("https://postman-echo.com/abc", "get?a=1&b=2") - if !assert.Equal(t, url, "https://postman-echo.com/abc/get?a=1&b=2") { + preparedURL = buildURL("https://postman-echo.com/abc", "get?a=1&b=2", nil) + if !assert.Equal(t, preparedURL.String(), "https://postman-echo.com/abc/get?a=1&b=2") { t.Fatal() } // omit query string in base url - url = buildURL("https://postman-echo.com/abc?x=6&y=9", "/get?a=1&b=2") - if !assert.Equal(t, url, "https://postman-echo.com/abc/get?a=1&b=2") { + preparedURL = buildURL("https://postman-echo.com/abc?x=6&y=9", "/get?a=1&b=2", nil) + if !assert.Equal(t, preparedURL.String(), "https://postman-echo.com/abc/get?a=1&b=2") { t.Fatal() } - url = buildURL("", "https://postman-echo.com/get") - if !assert.Equal(t, url, "https://postman-echo.com/get/") { + preparedURL = buildURL("", "https://postman-echo.com/get", nil) + if !assert.Equal(t, preparedURL.String(), "https://postman-echo.com/get/") { t.Fatal() } // notice: step request url > config base url - url = buildURL("https://postman-echo.com", "https://httpbin.org/get") - if !assert.Equal(t, url, "https://httpbin.org/get/") { + preparedURL = buildURL("https://postman-echo.com", "https://httpbin.org/get", nil) + if !assert.Equal(t, preparedURL.String(), "https://httpbin.org/get/") { t.Fatal() } // websocket url - url = buildURL("wss://ws.postman-echo.com/raw", "") - if !assert.Equal(t, url, "wss://ws.postman-echo.com/raw/") { + preparedURL = buildURL("wss://ws.postman-echo.com/raw", "", nil) + if !assert.Equal(t, preparedURL.String(), "wss://ws.postman-echo.com/raw/") { t.Fatal() } - url = buildURL("wss://ws.postman-echo.com", "/raw") - if !assert.Equal(t, url, "wss://ws.postman-echo.com/raw/") { + preparedURL = buildURL("wss://ws.postman-echo.com", "/raw", nil) + if !assert.Equal(t, preparedURL.String(), "wss://ws.postman-echo.com/raw/") { t.Fatal() } - url = buildURL("wss://ws.postman-echo.com/raw", "ws://echo.websocket.events") - if !assert.Equal(t, url, "ws://echo.websocket.events/") { + preparedURL = buildURL("wss://ws.postman-echo.com/raw", "ws://echo.websocket.events", nil) + if !assert.Equal(t, preparedURL.String(), "ws://echo.websocket.events/") { + t.Fatal() + } + + queryParams := url.Values{} + queryParams.Add("c", "3") + queryParams.Add("d", "4") + preparedURL = buildURL("https://postman-echo.com/", "/get/", queryParams) + if !assert.Equal(t, preparedURL.String(), "https://postman-echo.com/get?c=3&d=4") { + t.Fatal() + } + preparedURL = buildURL("https://postman-echo.com/abc", "get?a=1&b=2", queryParams) + if !assert.Equal(t, preparedURL.String(), "https://postman-echo.com/abc/get?a=1&b=2&c=3&d=4") { t.Fatal() } } diff --git a/hrp/step_request.go b/hrp/step_request.go index 4c4c61e1..6d672a3c 100644 --- a/hrp/step_request.go +++ b/hrp/step_request.go @@ -149,9 +149,8 @@ func (r *requestBuilder) prepareUrlParams(stepVariables map[string]interface{}) } var baseURL string if stepVariables["base_url"] != nil { - baseURL = stepVariables["base_url"].(string) + baseURL, _ = stepVariables["base_url"].(string) } - rawUrl := buildURL(baseURL, convertString(requestUrl)) // prepare request params var queryParams url.Values @@ -161,35 +160,24 @@ func (r *requestBuilder) prepareUrlParams(stepVariables map[string]interface{}) return errors.Wrap(err, "parse request params failed") } parsedParams := params.(map[string]interface{}) - r.requestMap["params"] = parsedParams if len(parsedParams) > 0 { queryParams = make(url.Values) for k, v := range parsedParams { queryParams.Add(k, convertString(v)) } } - } - if queryParams != nil { - // append params to url - paramStr := queryParams.Encode() - if strings.IndexByte(rawUrl, '?') == -1 { - rawUrl = strings.TrimRight(rawUrl, "/") + "?" + paramStr - } else { - rawUrl = rawUrl + "&" + paramStr - } + + // request params has been appended to url, thus delete it here + delete(r.requestMap, "params") } // prepare url - u, err := url.Parse(rawUrl) - if err != nil { - return errors.Wrap(err, "parse url failed") - } - r.req.URL = u - r.req.Host = u.Host + preparedURL := buildURL(baseURL, convertString(requestUrl), queryParams) + r.req.URL = preparedURL + r.req.Host = preparedURL.Host // update url - r.requestMap["url"] = u.String() - + r.requestMap["url"] = preparedURL.String() return nil } @@ -340,43 +328,14 @@ func runStepRequest(r *SessionRunner, step *TStep) (stepResult *StepResult, err // add request object to step variables, could be used in setup hooks stepVariables["hrp_step_name"] = step.Name stepVariables["hrp_step_request"] = rb.requestMap - stepVariables["request"] = rb.requestMap + stepVariables["request"] = rb.requestMap // setup hooks compatible with v3 // deal with setup hooks for _, setupHook := range step.SetupHooks { - req, err := parser.Parse(setupHook, stepVariables) + _, err := parser.Parse(setupHook, stepVariables) if err != nil { return stepResult, errors.Wrap(err, "run setup hooks failed") } - reqMap, ok := req.(map[string]interface{}) - if ok && reqMap != nil { - rb.requestMap = reqMap - stepVariables["request"] = reqMap - } - } - if len(step.SetupHooks) > 0 { - requestBody, ok := rb.requestMap["body"].(map[string]interface{}) - if ok { - body, err := json.Marshal(requestBody) - if err == nil { - rb.req.Body = io.NopCloser(bytes.NewReader(body)) - rb.req.ContentLength = int64(len(body)) - } - } - requestParams, ok := rb.requestMap["params"].(map[string]interface{}) - if ok { - params, err := json.Marshal(requestParams) - if err == nil { - rb.req.URL.RawQuery = string(params) - } - } - requestHeaders, ok := rb.requestMap["headers"].(map[string]interface{}) - if ok { - rb.req.Header = http.Header{} - for k, v := range requestHeaders { - rb.req.Header.Set(k, v.(string)) - } - } } // log & print request @@ -451,15 +410,10 @@ func runStepRequest(r *SessionRunner, step *TStep) (stepResult *StepResult, err // deal with teardown hooks for _, teardownHook := range step.TeardownHooks { - res, err := parser.Parse(teardownHook, stepVariables) + _, err := parser.Parse(teardownHook, stepVariables) if err != nil { return stepResult, errors.Wrap(err, "run teardown hooks failed") } - resMpa, ok := res.(map[string]interface{}) - if ok { - stepVariables["response"] = resMpa - respObj.respObjMeta = resMpa - } } sessionData.ReqResps.Request = rb.requestMap