Skip to content

Commit

Permalink
refactor: deduplicate clone request code
Browse files Browse the repository at this point in the history
  • Loading branch information
jooola committed Jun 19, 2024
1 parent 77a55aa commit 33e9b77
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 14 deletions.
15 changes: 15 additions & 0 deletions hcloud/client_handler.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package hcloud

import (
"context"
"net/http"
)

Expand Down Expand Up @@ -39,3 +40,17 @@ func assembleHandlerChain(client *Client) handler {

return h
}

// cloneRequest clones both the request and the request body.
func cloneRequest(req *http.Request, ctx context.Context) (cloned *http.Request, err error) { //revive:disable:context-as-argument
cloned = req.Clone(ctx)

if req.ContentLength > 0 {
cloned.Body, err = req.GetBody()
if err != nil {
return nil, err
}
}

return cloned, nil
}
10 changes: 3 additions & 7 deletions hcloud/client_handler_debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,9 @@ type debugHandler struct {
func (h *debugHandler) Do(req *http.Request, v any) (resp *Response, err error) {
// Clone the request, so we can redact the auth header, read the body
// and use a new context.
cloned := req.Clone(context.Background())

if req.ContentLength > 0 {
cloned.Body, err = req.GetBody()
if err != nil {
return nil, err
}
cloned, err := cloneRequest(req, context.Background())
if err != nil {
return nil, err
}

cloned.Header.Set("Authorization", "REDACTED")
Expand Down
10 changes: 3 additions & 7 deletions hcloud/client_handler_retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,9 @@ func (h *retryHandler) Do(req *http.Request, v any) (resp *Response, err error)

for {
// Clone the request using the original context
cloned := req.Clone(req.Context())

if req.ContentLength > 0 {
cloned.Body, err = req.GetBody()
if err != nil {
return nil, err
}
cloned, err := cloneRequest(req, req.Context())
if err != nil {
return nil, err
}

resp, err = h.handler.Do(cloned, v)
Expand Down
28 changes: 28 additions & 0 deletions hcloud/client_handler_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package hcloud

import (
"bytes"
"context"
"io"
"net/http"
"net/http/httptest"
"testing"

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

Expand Down Expand Up @@ -33,3 +37,27 @@ func fakeResponse(t *testing.T, statusCode int, body string, json bool) *Respons

return resp
}

func TestCloneRequest(t *testing.T) {
ctx := context.Background()

req, err := http.NewRequest("GET", "/", bytes.NewBufferString("Hello"))
require.NoError(t, err)
req.Header.Set("Authorization", "sensitive")

cloned, err := cloneRequest(req, ctx)
require.NoError(t, err)
cloned.Header.Set("Authorization", "REDACTED")
cloned.Body = io.NopCloser(bytes.NewBufferString("Changed"))

// Check context
assert.Equal(t, req.Context(), cloned.Context())

// Check headers
assert.Equal(t, req.Header.Get("Authorization"), "sensitive")

// Check body
reqBody, err := io.ReadAll(req.Body)
require.NoError(t, err)
assert.Equal(t, string(reqBody), "Hello")
}

0 comments on commit 33e9b77

Please sign in to comment.