Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Headers interface #20

Merged
merged 1 commit into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ type client struct {
}

type Client interface {
Post(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error)
Put(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error)
Patch(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error)
Delete(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error)
Get(ctx context.Context, url string, headers map[string]string) (*http.Response, error)
Post(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error)
Put(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error)
Patch(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error)
Delete(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error)
Get(ctx context.Context, url string, headers Headers) (*http.Response, error)

Do(ctx context.Context, method Method, url string, body []byte, headers map[string]string) (*http.Response, error)
Do(ctx context.Context, method Method, url string, body []byte, headers Headers) (*http.Response, error)
}

// Create new Client instance
Expand All @@ -57,38 +57,38 @@ func New() Client {
}

// Send request with method POST
func (c *client) Post(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (c *client) Post(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
return c.Do(ctx, MethodPost, url, body, headers)
}

// Send request with method PUT
func (c *client) Put(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (c *client) Put(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
return c.Do(ctx, MethodPut, url, body, headers)
}

// Send request with method PATCH
func (c *client) Patch(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (c *client) Patch(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
return c.Do(ctx, MethodPatch, url, body, headers)
}

// Send request with method DELETE
func (c *client) Delete(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (c *client) Delete(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
return c.Do(ctx, MethodDelete, url, body, headers)
}

// Send request with method GET
func (c *client) Get(ctx context.Context, url string, headers map[string]string) (*http.Response, error) {
func (c *client) Get(ctx context.Context, url string, headers Headers) (*http.Response, error) {
return c.Do(ctx, MethodGet, url, nil, headers)
}

func (c *client) Do(ctx context.Context, method Method, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (c *client) Do(ctx context.Context, method Method, url string, body []byte, headers Headers) (*http.Response, error) {
request, err := http.NewRequestWithContext(ctx, string(method), url, bytes.NewBuffer(body))
if err != nil {
return nil, err
}

for key, value := range headers {
request.Header.Set(key, value)
for _, key := range headers.Keys() {
request.Header.Set(key, headers.Get(key))
}

request, cancel := c.setRequestTimeout(request)
Expand Down
40 changes: 20 additions & 20 deletions client/client_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ type MockedClient struct {
}

type Expecter interface {
ExpectPost(url string, body []byte, err error, response *http.Response, headers map[string]string)
ExpectPut(url string, body []byte, err error, response *http.Response, headers map[string]string)
ExpectPatch(url string, body []byte, err error, response *http.Response, headers map[string]string)
ExpectDelete(url string, body []byte, err error, response *http.Response, headers map[string]string)
ExpectGet(url string, err error, response *http.Response, headers map[string]string)
ExpectDo(url string, method Method, body []byte, err error, response *http.Response, headers map[string]string)
ExpectPost(url string, body []byte, err error, response *http.Response, headers Headers)
ExpectPut(url string, body []byte, err error, response *http.Response, headers Headers)
ExpectPatch(url string, body []byte, err error, response *http.Response, headers Headers)
ExpectDelete(url string, body []byte, err error, response *http.Response, headers Headers)
ExpectGet(url string, err error, response *http.Response, headers Headers)
ExpectDo(url string, method Method, body []byte, err error, response *http.Response, headers Headers)

AllExpectationsDone() error
Reset()
Expand All @@ -41,7 +41,7 @@ type mockClientData struct {
url string
body []byte
response *http.Response
headers map[string]string
headers Headers
err error
method Method
}
Expand All @@ -54,7 +54,7 @@ func NewMock() Mocker {
}

// Store expected call of Post method with expected data and error
func (m *MockedClient) ExpectDo(url string, method Method, body []byte, err error, response *http.Response, headers map[string]string) {
func (m *MockedClient) ExpectDo(url string, method Method, body []byte, err error, response *http.Response, headers Headers) {
m.history.Push("Do", &mockClientData{
url: url,
body: body,
Expand All @@ -66,7 +66,7 @@ func (m *MockedClient) ExpectDo(url string, method Method, body []byte, err erro
}

// Store expected call of Post method with expected data and error
func (m *MockedClient) ExpectPost(url string, body []byte, err error, response *http.Response, headers map[string]string) {
func (m *MockedClient) ExpectPost(url string, body []byte, err error, response *http.Response, headers Headers) {
m.history.Push("Post", &mockClientData{
url: url,
body: body,
Expand All @@ -78,7 +78,7 @@ func (m *MockedClient) ExpectPost(url string, body []byte, err error, response *
}

// Store expected call of Post method with expected data and error
func (m *MockedClient) ExpectPut(url string, body []byte, err error, response *http.Response, headers map[string]string) {
func (m *MockedClient) ExpectPut(url string, body []byte, err error, response *http.Response, headers Headers) {
m.history.Push("Put", &mockClientData{
url: url,
body: body,
Expand All @@ -90,7 +90,7 @@ func (m *MockedClient) ExpectPut(url string, body []byte, err error, response *h
}

// Store expected call of Post method with expected data and error
func (m *MockedClient) ExpectPatch(url string, body []byte, err error, response *http.Response, headers map[string]string) {
func (m *MockedClient) ExpectPatch(url string, body []byte, err error, response *http.Response, headers Headers) {
m.history.Push("Patch", &mockClientData{
url: url,
body: body,
Expand All @@ -102,7 +102,7 @@ func (m *MockedClient) ExpectPatch(url string, body []byte, err error, response
}

// Store expected call of Post method with expected data and error
func (m *MockedClient) ExpectDelete(url string, body []byte, err error, response *http.Response, headers map[string]string) {
func (m *MockedClient) ExpectDelete(url string, body []byte, err error, response *http.Response, headers Headers) {
m.history.Push("Delete", &mockClientData{
url: url,
body: body,
Expand All @@ -114,7 +114,7 @@ func (m *MockedClient) ExpectDelete(url string, body []byte, err error, response
}

// Store expected call of Get method with expected data and error
func (m *MockedClient) ExpectGet(url string, err error, response *http.Response, headers map[string]string) {
func (m *MockedClient) ExpectGet(url string, err error, response *http.Response, headers Headers) {
m.history.Push("Get", &mockClientData{
url: url,
body: nil,
Expand All @@ -136,7 +136,7 @@ func (m *MockedClient) Reset() {
}

// Check if call of Post method was expected and returning expected response and error
func (m *MockedClient) Post(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (m *MockedClient) Post(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
item, err := m.checkCall("Post", MethodPost, url, body, headers)
if err != nil {
return nil, err
Expand All @@ -146,7 +146,7 @@ func (m *MockedClient) Post(ctx context.Context, url string, body []byte, header
}

// Check if call of Post method was expected and returning expected response and error
func (m *MockedClient) Put(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (m *MockedClient) Put(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
item, err := m.checkCall("Put", MethodPut, url, body, headers)
if err != nil {
return nil, err
Expand All @@ -156,7 +156,7 @@ func (m *MockedClient) Put(ctx context.Context, url string, body []byte, headers
}

// Check if call of Post method was expected and returning expected response and error
func (m *MockedClient) Patch(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (m *MockedClient) Patch(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
item, err := m.checkCall("Patch", MethodPatch, url, body, headers)
if err != nil {
return nil, err
Expand All @@ -166,7 +166,7 @@ func (m *MockedClient) Patch(ctx context.Context, url string, body []byte, heade
}

// Check if call of Post method was expected and returning expected response and error
func (m *MockedClient) Delete(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (m *MockedClient) Delete(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
item, err := m.checkCall("Delete", MethodDelete, url, body, headers)
if err != nil {
return nil, err
Expand All @@ -176,7 +176,7 @@ func (m *MockedClient) Delete(ctx context.Context, url string, body []byte, head
}

// Check if call of Get method was expected and returning expected response and error
func (m *MockedClient) Get(ctx context.Context, url string, headers map[string]string) (*http.Response, error) {
func (m *MockedClient) Get(ctx context.Context, url string, headers Headers) (*http.Response, error) {
item, err := m.checkCall("Get", MethodGet, url, nil, headers)
if err != nil {
return nil, err
Expand All @@ -185,7 +185,7 @@ func (m *MockedClient) Get(ctx context.Context, url string, headers map[string]s
return item.Data.response, item.Data.err
}

func (m *MockedClient) Do(ctx context.Context, method Method, url string, body []byte, headers map[string]string) (*http.Response, error) {
func (m *MockedClient) Do(ctx context.Context, method Method, url string, body []byte, headers Headers) (*http.Response, error) {
item, err := m.checkCall("Do", method, url, body, headers)
if err != nil {
return nil, err
Expand All @@ -195,7 +195,7 @@ func (m *MockedClient) Do(ctx context.Context, method Method, url string, body [
}

// Check if call of method was expected and returning expected data of this call
func (m *MockedClient) checkCall(name string, method Method, url string, body []byte, headers map[string]string) (*mock.MockHistoryItem[*mockClientData], error) {
func (m *MockedClient) checkCall(name string, method Method, url string, body []byte, headers Headers) (*mock.MockHistoryItem[*mockClientData], error) {
item, err := m.history.Get(name)
if err != nil {
return nil, err
Expand Down
20 changes: 10 additions & 10 deletions client/client_mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,46 +71,46 @@ func TestMockHttpUtil(t *testing.T) {
var testMethods = []struct {
name string
method string
expectFunc func(url string, body []byte, err error, response *http.Response, headers map[string]string)
executor func(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error)
expectFunc func(url string, body []byte, err error, response *http.Response, headers Headers)
executor func(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error)
}{
{
name: "Post",
method: http.MethodPost,
expectFunc: func(url string, body []byte, err error, response *http.Response, headers map[string]string) {
expectFunc: func(url string, body []byte, err error, response *http.Response, headers Headers) {
mockClient.ExpectPost(url, body, err, response, headers)
},
executor: func(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
executor: func(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
return mockClient.Post(ctx, url, body, headers)
},
},
{
name: "Put",
method: http.MethodPut,
expectFunc: func(url string, body []byte, err error, response *http.Response, headers map[string]string) {
expectFunc: func(url string, body []byte, err error, response *http.Response, headers Headers) {
mockClient.ExpectPut(url, body, err, response, headers)
},
executor: func(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
executor: func(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
return mockClient.Put(ctx, url, body, headers)
},
},
{
name: "Patch",
method: http.MethodPatch,
expectFunc: func(url string, body []byte, err error, response *http.Response, headers map[string]string) {
expectFunc: func(url string, body []byte, err error, response *http.Response, headers Headers) {
mockClient.ExpectPatch(url, body, err, response, headers)
},
executor: func(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
executor: func(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
return mockClient.Patch(ctx, url, body, headers)
},
},
{
name: "Delete",
method: http.MethodDelete,
expectFunc: func(url string, body []byte, err error, response *http.Response, headers map[string]string) {
expectFunc: func(url string, body []byte, err error, response *http.Response, headers Headers) {
mockClient.ExpectDelete(url, body, err, response, headers)
},
executor: func(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error) {
executor: func(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error) {
return mockClient.Delete(ctx, url, body, headers)
},
},
Expand Down
14 changes: 7 additions & 7 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestPost(t *testing.T) {
var tests = []struct {
name string
method string
executor func(ctx context.Context, url string, body []byte, headers map[string]string) (*http.Response, error)
executor func(ctx context.Context, url string, body []byte, headers Headers) (*http.Response, error)
}{
{
name: "Post",
Expand Down Expand Up @@ -54,9 +54,9 @@ func TestPost(t *testing.T) {
// Create request
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
reqHeaders := map[string]string{
reqHeaders := NewHeaders(map[string]string{
"Content-Type": "application/json",
}
})

resp, err := test.executor(ctx, server.URL, []byte(`{"key":"value"}`), reqHeaders)
if err != nil {
Expand All @@ -83,9 +83,9 @@ func TestGet(t *testing.T) {
// Create request
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
reqHeaders := map[string]string{
reqHeaders := NewHeaders(map[string]string{
"Accept": "application/json",
}
})

// Call Get method
resp, err := c.Get(ctx, server.URL, reqHeaders)
Expand Down Expand Up @@ -121,9 +121,9 @@ func TestGetWithTimeout(t *testing.T) {
// Create request with a timeout shorter than the server delay
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
reqHeaders := map[string]string{
reqHeaders := NewHeaders(map[string]string{
"Accept": "application/json",
}
})

// Call Get method
_, err := c.Get(ctx, server.URL, reqHeaders)
Expand Down
37 changes: 37 additions & 0 deletions client/headers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package client

type Headers interface {
Set(key, value string)
Keys() []string
Get(key string) string
Value() map[string]string
}

type HeadersStore map[string]string

func NewHeaders(h map[string]string) Headers {
if h == nil {
h = make(HeadersStore)
}
return HeadersStore(h)
}

func (h HeadersStore) Set(key, value string) {
h[key] = value
}

func (h HeadersStore) Keys() []string {
keys := make([]string, 0, len(h))
for k := range h {
keys = append(keys, k)
}
return keys
}

func (h HeadersStore) Get(key string) string {
return h[key]
}

func (h HeadersStore) Value() map[string]string {
return h
}
39 changes: 39 additions & 0 deletions client/headers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package client

import (
"sort"
"testing"

"github.com/stretchr/testify/assert"
)

func TestHeaders(t *testing.T) {

t.Run("not empty init state", func(t *testing.T) {
headerName1 := "header1"
headerValue1 := "value1"
initState := map[string]string{
headerName1: headerValue1,
}
headers := NewHeaders(initState)
headerName2 := "test-header"
headerValue2 := "header-value"
headers.Set(headerName2, headerValue2)
assert.Equal(t, headerValue1, headers.Get(headerName1))
assert.Equal(t, headerValue2, headers.Get(headerName2))
keys := headers.Keys()
sort.Strings(keys)
assert.Equal(t, []string{headerName1, headerName2}, keys)
assert.Equal(t, map[string]string{headerName1: headerValue1, headerName2: headerValue2}, headers.Value())
})

t.Run("empty init state", func(t *testing.T) {
headers := NewHeaders(nil)
headerName := "test-header"
headerValue := "header-value"
headers.Set(headerName, headerValue)
assert.Equal(t, headerValue, headers.Get(headerName))
assert.Equal(t, []string{headerName}, headers.Keys())
assert.Equal(t, map[string]string{headerName: headerValue}, headers.Value())
})
}
Loading