Skip to content

Commit 84e0aca

Browse files
authored
feat(pkg/httpstatuschecker): allow custom http.Client (#4869)
* feat: improve the `httpstatuschecker` by injecting clients * add changelog
1 parent a94b29a commit 84e0aca

File tree

5 files changed

+90
-17
lines changed

5 files changed

+90
-17
lines changed

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
- [#4864](https://github.com/ignite/cli/pull/4864) Mismatch for message names.
88
- [#4735](https://github.com/ignite/cli/issues/4735) Cleanup `xgenny` runner to avoid duplicated generators.
99

10+
## Features
11+
12+
- [#4869](https://github.com/ignite/cli/pull/4869) Improve the httpstatuschecker by injecting clients.
13+
1014
## [`v29.7.0`](https://github.com/ignite/cli/releases/tag/v29.7.0)
1115

1216
## Changes

ignite/pkg/httpstatuschecker/httpstatuschecker.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ func Method(name string) Option {
2222
}
2323
}
2424

25+
// Client configures http client.
26+
func Client(client *http.Client) Option {
27+
return func(cr *checker) {
28+
if client != nil {
29+
cr.c = client
30+
}
31+
}
32+
}
33+
2534
// Check checks if given http addr is alive by applying options.
2635
func Check(ctx context.Context, addr string, options ...Option) (isAvailable bool, err error) {
2736
cr := &checker{
Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
package httpstatuschecker
22

33
import (
4+
"bytes"
45
"context"
6+
"errors"
7+
"io"
58
"net/http"
6-
"net/http/httptest"
79
"testing"
810

911
"github.com/stretchr/testify/require"
1012
)
1113

14+
type roundTripperFunc func(*http.Request) (*http.Response, error)
15+
16+
func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
17+
return f(req)
18+
}
19+
20+
func newTestClient(fn roundTripperFunc) *http.Client {
21+
return &http.Client{Transport: fn}
22+
}
23+
1224
func TestCheckStatus(t *testing.T) {
1325
cases := []struct {
1426
name string
@@ -21,20 +33,28 @@ func TestCheckStatus(t *testing.T) {
2133
}
2234
for _, tt := range cases {
2335
t.Run(tt.name, func(t *testing.T) {
24-
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
25-
w.WriteHeader(tt.returnedStatus)
26-
}))
27-
defer ts.Close()
36+
client := newTestClient(func(req *http.Request) (*http.Response, error) {
37+
return &http.Response{
38+
StatusCode: tt.returnedStatus,
39+
Body: io.NopCloser(bytes.NewReader(nil)),
40+
Header: make(http.Header),
41+
ContentLength: 0,
42+
Request: req,
43+
}, nil
44+
})
2845

29-
isAvailable, err := Check(context.Background(), ts.URL)
46+
isAvailable, err := Check(context.Background(), "http://example.com", Client(client))
3047
require.NoError(t, err)
3148
require.Equal(t, tt.isAvaiable, isAvailable)
3249
})
3350
}
3451
}
3552

3653
func TestCheckServerUnreachable(t *testing.T) {
37-
isAvailable, err := Check(context.Background(), "http://localhost:63257")
54+
client := newTestClient(func(*http.Request) (*http.Response, error) {
55+
return nil, errors.New("dial tcp: connection refused")
56+
})
57+
isAvailable, err := Check(context.Background(), "http://example.com", Client(client))
3858
require.NoError(t, err)
3959
require.False(t, isAvailable)
4060
}

ignite/pkg/jsonfile/jsonfile.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ func FromPath(path string) (*JSONFile, error) {
8787
// tarballFileName is extracted from it and is returned instead of the URL
8888
// content.
8989
func FromURL(ctx context.Context, url, destPath, tarballFileName string) (*JSONFile, error) {
90+
return fromURL(ctx, url, destPath, tarballFileName, http.DefaultClient)
91+
}
92+
93+
// FromURLWithClient fetches the file using the provided HTTP client.
94+
// If client is nil, http.DefaultClient is used.
95+
func FromURLWithClient(ctx context.Context, url, destPath, tarballFileName string, client *http.Client) (*JSONFile, error) {
96+
if client == nil {
97+
client = http.DefaultClient
98+
}
99+
return fromURL(ctx, url, destPath, tarballFileName, client)
100+
}
101+
102+
func fromURL(ctx context.Context, url, destPath, tarballFileName string, client *http.Client) (*JSONFile, error) {
90103
// TODO create a cache system to avoid download genesis with the same hash again
91104

92105
// Download the file from URL
@@ -95,7 +108,7 @@ func FromURL(ctx context.Context, url, destPath, tarballFileName string) (*JSONF
95108
return nil, err
96109
}
97110

98-
resp, err := http.DefaultClient.Do(req)
111+
resp, err := client.Do(req)
99112
if err != nil {
100113
return nil, err
101114
}

ignite/pkg/jsonfile/jsonfile_test.go

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import (
55
"context"
66
"encoding/json"
77
"fmt"
8+
"io"
89
"net/http"
9-
"net/http/httptest"
1010
"os"
1111
"reflect"
1212
"testing"
@@ -19,6 +19,26 @@ import (
1919
"github.com/ignite/cli/v29/ignite/pkg/tarball"
2020
)
2121

22+
type roundTripperFunc func(*http.Request) (*http.Response, error)
23+
24+
func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
25+
return f(req)
26+
}
27+
28+
func newTestClient(statusCode int, body []byte) *http.Client {
29+
return &http.Client{
30+
Transport: roundTripperFunc(func(req *http.Request) (*http.Response, error) {
31+
return &http.Response{
32+
StatusCode: statusCode,
33+
Body: io.NopCloser(bytes.NewReader(body)),
34+
Header: make(http.Header),
35+
ContentLength: int64(len(body)),
36+
Request: req,
37+
}, nil
38+
}),
39+
}
40+
}
41+
2242
func TestJSONFile_Field(t *testing.T) {
2343
type (
2444
invalidStruct struct {
@@ -356,17 +376,24 @@ func TestFromURL(t *testing.T) {
356376
t.Run(tt.name, func(t *testing.T) {
357377
url := tt.args.url
358378
if url == "" {
359-
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
360-
file, err := os.ReadFile(tt.args.filepath)
361-
require.NoError(t, err)
362-
_, err = w.Write(file)
363-
require.NoError(t, err)
364-
}))
365-
url = ts.URL
379+
url = "https://example.com/testdata"
380+
}
381+
382+
var body []byte
383+
if tt.args.filepath != "" {
384+
var err error
385+
body, err = os.ReadFile(tt.args.filepath)
386+
require.NoError(t, err)
387+
}
388+
389+
statusCode := http.StatusOK
390+
if tt.err == ErrInvalidURL {
391+
statusCode = http.StatusNotFound
366392
}
393+
client := newTestClient(statusCode, body)
367394

368395
filepath := fmt.Sprintf("%s/jsonfile.json", t.TempDir())
369-
got, err := FromURL(context.TODO(), url, filepath, tt.args.tarballFileName)
396+
got, err := FromURLWithClient(context.TODO(), url, filepath, tt.args.tarballFileName, client)
370397
if tt.err != nil {
371398
require.Error(t, err)
372399
require.ErrorIs(t, err, tt.err)

0 commit comments

Comments
 (0)