From b7e3d35ee6e075a3a4af8e5f798d6cfc53dc89f6 Mon Sep 17 00:00:00 2001 From: Jeevanandam M Date: Thu, 14 Nov 2024 23:25:48 -0800 Subject: [PATCH] feat: add request funcs method for request composition Co-authored-by: thinkgo --- client.go | 3 +++ request.go | 27 +++++++++++++++++++++++++++ request_test.go | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/client.go b/client.go index 4c9ef204..75c6c83d 100644 --- a/client.go +++ b/client.go @@ -97,6 +97,9 @@ type ( // SuccessHook type is for reacting to request success SuccessHook func(*Client, *Response) + // RequestFunc type is for extended manipulation of the Request instance + RequestFunc func(*Request) *Request + // TLSClientConfiger interface is to configure TLS Client configuration on custom transport // implemented using [http.RoundTripper] TLSClientConfiger interface { diff --git a/request.go b/request.go index 63925915..0261f27a 100644 --- a/request.go +++ b/request.go @@ -1437,6 +1437,33 @@ func (r *Request) Clone(ctx context.Context) *Request { return rr } +// Funcs method gets executed on request composition that passes the +// current request instance to provided [RequestFunc], which could be +// used to apply common/reusable logic to the given request instance. +// +// func addRequestContentType(r *Request) *Request { +// return r.SetHeader("Content-Type", "application/json"). +// SetHeader("Accept", "application/json") +// } +// +// func addRequestQueryParams(page, size int) func(r *Request) *Request { +// return func(r *Request) *Request { +// return r.SetQueryParam("page", strconv.Itoa(page)). +// SetQueryParam("size", strconv.Itoa(size)). +// SetQueryParam("request_no", strconv.Itoa(int(time.Now().Unix()))) +// } +// } +// +// client.R(). +// Funcs(addRequestContentType, addRequestQueryParams(1, 100)). +// Get("https://localhost:8080/foobar") +func (r *Request) Funcs(funcs ...RequestFunc) *Request { + for _, f := range funcs { + r = f(r) + } + return r +} + func (r *Request) fmtBodyString(sl int) (body string) { body = "***** NO CONTENT *****" if !r.isPayloadSupported() { diff --git a/request_test.go b/request_test.go index 73edf6af..e5db7f60 100644 --- a/request_test.go +++ b/request_test.go @@ -2201,6 +2201,40 @@ func TestRequestSetResultAndSetOutputFile(t *testing.T) { assertEqual(t, `{ "id": "success", "message": "login successful" }`, string(fileContent)) } +func TestRequestFuncs(t *testing.T) { + ts := createGetServer(t) + defer ts.Close() + + c := dcnl(). + SetQueryParam("client_param", "true"). + SetQueryParams(map[string]string{"req_1": "value1", "req_3": "value3"}). + SetDebug(true) + + addRequestQueryParams := func(page, size int) func(r *Request) *Request { + return func(r *Request) *Request { + return r.SetQueryParam("page", strconv.Itoa(page)). + SetQueryParam("size", strconv.Itoa(size)). + SetQueryParam("request_no", strconv.Itoa(int(time.Now().Unix()))) + } + } + + addRequestHeaders := func(r *Request) *Request { + return r.SetHeader(hdrAcceptKey, "application/json"). + SetHeader(hdrUserAgentKey, "my-client/v1.0") + } + + resp, err := c.R(). + Funcs(addRequestQueryParams(1, 100), addRequestHeaders). + SetHeader(hdrUserAgentKey, "Test Custom User agent"). + Get(ts.URL + "/") + + assertError(t, err) + assertEqual(t, http.StatusOK, resp.StatusCode()) + assertEqual(t, "HTTP/1.1", resp.Proto()) + assertEqual(t, "200 OK", resp.Status()) + assertEqual(t, "TestGet: text response", resp.String()) +} + // This test methods exist for test coverage purpose // to validate the getter and setter func TestRequestSettingsCoverage(t *testing.T) {