diff --git a/internal/common/client.go b/internal/common/client.go index 01c3beb..92cf11f 100644 --- a/internal/common/client.go +++ b/internal/common/client.go @@ -122,12 +122,20 @@ func (dsp *DefaultSessionProvider) Invalidate() { } type Client struct { - Url string - httpClient *http.Client - clientCode string - partnerKey string - headersFunc AuthFunc - sessionProvider SessionProvider + Url string + httpClient *http.Client + clientCode string + partnerKey string + headersFunc AuthFunc + sessionProvider SessionProvider + sendParametersInRequestBody bool +} + +//SendParametersInRequestBody indicates to the client that the request should add the data payload in the +//request body instead of using the query parameters. Using the request body eliminates the query size +//limitations imposed by the maximum URL length +func (cli *Client) SendParametersInRequestBody() { + cli.sendParametersInRequestBody = true } func (cli *Client) Close() { diff --git a/internal/common/util.go b/internal/common/util.go index b25c5e5..ca00050 100644 --- a/internal/common/util.go +++ b/internal/common/util.go @@ -4,13 +4,14 @@ import ( "context" "encoding/json" "fmt" - "github.com/erply/api-go-wrapper/pkg/api/common" - "github.com/erply/api-go-wrapper/pkg/api/log" "io" "io/ioutil" "net/http" "net/url" "strings" + + "github.com/erply/api-go-wrapper/pkg/api/common" + "github.com/erply/api-go-wrapper/pkg/api/log" ) type BulkInput struct { @@ -56,22 +57,32 @@ func setParams(params url.Values, filters map[string]string) { func (cli *Client) SendRequest(ctx context.Context, apiMethod string, filters map[string]string) (*http.Response, error) { log.Log.Log(log.Debug, "will call %s with filters %+v", apiMethod, filters) - req, err := getHTTPRequest(cli, nil) - if err != nil { - return nil, common.NewFromError("failed to build http request", err, 0) - } - req = req.WithContext(ctx) params := cli.headersFunc(apiMethod) log.Log.Log(log.Debug, "extracted headers %+v", params) - params, err = cli.addSessionParams(params) + params, err := cli.addSessionParams(params) if err != nil { return nil, err } setParams(params, filters) - req.URL.RawQuery = params.Encode() + var req *http.Request + if cli.sendParametersInRequestBody { + req, err = getHTTPRequest(cli, strings.NewReader(params.Encode())) + if err != nil { + return nil, common.NewFromError("failed to build http request", err, 0) + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + } else { + req, err = getHTTPRequest(cli, nil) + if err != nil { + return nil, common.NewFromError("failed to build http request", err, 0) + } + req.URL.RawQuery = params.Encode() + } + req = req.WithContext(ctx) + resp, err := doRequest(req, cli) if err != nil { return nil, common.NewFromError(fmt.Sprintf("%v request failed", apiMethod), err, 0) diff --git a/internal/common/util_test.go b/internal/common/util_test.go index bc5cbba..fcc14cf 100644 --- a/internal/common/util_test.go +++ b/internal/common/util_test.go @@ -2,13 +2,93 @@ package common import ( "context" - "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" "testing" "time" + + "github.com/stretchr/testify/assert" ) +func TestSendRequestInBody(t *testing.T) { + calledTimes := 0 + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + calledTimes++ + assert.Equal(t, "", r.URL.Query().Get("clientCode")) + assert.Equal(t, "", r.URL.Query().Get("sessionKey")) + assert.Equal(t, "", r.URL.Query().Get("someKey")) + AssertFormValues(t, r, map[string]interface{}{ + "clientCode": "someclient", + "sessionKey": "somesess", + "someKey": "someValue", + }) + })) + defer srv.Close() + + cli := NewClientWithURL( + "somesess", + "someclient", + "", + srv.URL, + &http.Client{ + Timeout: 5 * time.Second, + }, + nil, + ) + cli.SendParametersInRequestBody() + + resp, err := cli.SendRequest( + context.Background(), + "getSuppliers", + map[string]string{"someKey": "someValue"}, + ) + assert.NoError(t, err) + if err != nil { + return + } + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, 1, calledTimes) +} + +func TestSendRequestInQuery(t *testing.T) { + calledTimes := 0 + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + calledTimes++ + assert.Equal(t, "someclient", r.URL.Query().Get("clientCode")) + assert.Equal(t, "somesess", r.URL.Query().Get("sessionKey")) + assert.Equal(t, "someValue", r.URL.Query().Get("someKey")) + AssertFormValues(t, r, map[string]interface{}{ + "clientCode": "someclient", + "sessionKey": "somesess", + "someKey": "someValue", + }) + })) + defer srv.Close() + + cli := NewClientWithURL( + "somesess", + "someclient", + "", + srv.URL, + &http.Client{ + Timeout: 5 * time.Second, + }, + nil, + ) + + resp, err := cli.SendRequest( + context.Background(), + "getSuppliers", + map[string]string{"someKey": "someValue"}, + ) + assert.NoError(t, err) + if err != nil { + return + } + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, 1, calledTimes) +} + func TestSendRequestBulk(t *testing.T) { calledTimes := 0 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/api/addresses/addressRequests_test.go b/pkg/api/addresses/addressRequests_test.go index c89d155..0f31551 100644 --- a/pkg/api/addresses/addressRequests_test.go +++ b/pkg/api/addresses/addressRequests_test.go @@ -3,12 +3,13 @@ package addresses import ( "context" "encoding/json" - "github.com/erply/api-go-wrapper/internal/common" - sharedCommon "github.com/erply/api-go-wrapper/pkg/api/common" - "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" "testing" + + "github.com/erply/api-go-wrapper/internal/common" + sharedCommon "github.com/erply/api-go-wrapper/pkg/api/common" + "github.com/stretchr/testify/assert" ) func TestGetAddresses(t *testing.T) { @@ -279,12 +280,12 @@ func TestGetAddressesBulkCustomUnmarshal(t *testing.T) { { AddressID: 123, Address: "Some Address 123", - TypeID: "3", + TypeID: 3, }, { AddressID: 124, Address: "Some Address 124", - TypeID: "4", + TypeID: 4, }, }, suppliersBulk.BulkItems[0].Addresses) @@ -294,7 +295,7 @@ func TestGetAddressesBulkCustomUnmarshal(t *testing.T) { { AddressID: 125, Address: "Some Address 125", - TypeID: "5", + TypeID: 5, }, }, suppliersBulk.BulkItems[1].Addresses) assert.Equal(t, expectedStatus, suppliersBulk.BulkItems[1].Status) diff --git a/pkg/api/client.go b/pkg/api/client.go index 75cec73..cb60c4d 100644 --- a/pkg/api/client.go +++ b/pkg/api/client.go @@ -4,6 +4,12 @@ import ( "encoding/json" "errors" "fmt" + "net/http" + "net/url" + "strconv" + "sync" + "time" + "github.com/erply/api-go-wrapper/internal/common" "github.com/erply/api-go-wrapper/pkg/api/addresses" "github.com/erply/api-go-wrapper/pkg/api/auth" @@ -18,11 +24,6 @@ import ( "github.com/erply/api-go-wrapper/pkg/api/sales" "github.com/erply/api-go-wrapper/pkg/api/servicediscovery" "github.com/erply/api-go-wrapper/pkg/api/warehouse" - "net/http" - "net/url" - "strconv" - "sync" - "time" ) type Client struct { @@ -59,6 +60,13 @@ func (cl *Client) GetSession() (sessionKey string, err error) { return cl.commonClient.GetSession() } +//SendParametersInRequestBody indicates to the client that the request should add the data payload in the +//request body instead of using the query parameters. Using the request body eliminates the query size +//limitations imposed by the maximum URL length +func (cl *Client) SendParametersInRequestBody() { + cl.commonClient.SendParametersInRequestBody() +} + //NewUnvalidatedClient returns a new Client without validating any of the incoming parameters giving the //developer more flexibility func NewUnvalidatedClient(sk, cc, partnerKey string, httpCli *http.Client) *Client {