Skip to content

Commit b02c7a8

Browse files
added context timeout configuration for API requests (#331)
* added context timeout configuration for API requests
1 parent f5fe357 commit b02c7a8

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

client/nginx.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var (
3535
defaultBackup = false
3636
defaultDown = false
3737
defaultWeight = 1
38+
defaultTimeout = 10 * time.Second
3839
)
3940

4041
// ErrUnsupportedVer means that client's API version is not supported by NGINX plus API.
@@ -46,6 +47,7 @@ type NginxClient struct {
4647
apiEndpoint string
4748
apiVersion int
4849
checkAPI bool
50+
ctxTimeout time.Duration
4951
}
5052

5153
type Option func(*NginxClient)
@@ -546,13 +548,21 @@ func WithCheckAPI() Option {
546548
}
547549
}
548550

551+
// WithTimeout sets the timeout per request for the client.
552+
func WithTimeout(duration time.Duration) Option {
553+
return func(o *NginxClient) {
554+
o.ctxTimeout = duration
555+
}
556+
}
557+
549558
// NewNginxClient creates a new NginxClient.
550559
func NewNginxClient(apiEndpoint string, opts ...Option) (*NginxClient, error) {
551560
c := &NginxClient{
552561
httpClient: http.DefaultClient,
553562
apiEndpoint: apiEndpoint,
554563
apiVersion: APIVersion,
555564
checkAPI: false,
565+
ctxTimeout: defaultTimeout,
556566
}
557567

558568
for _, opt := range opts {
@@ -567,8 +577,12 @@ func NewNginxClient(apiEndpoint string, opts ...Option) (*NginxClient, error) {
567577
return nil, fmt.Errorf("API version %v is not supported by the client", c.apiVersion)
568578
}
569579

580+
if c.ctxTimeout <= 0 {
581+
return nil, fmt.Errorf("timeout has to be greater than 0 %v", c.ctxTimeout)
582+
}
583+
570584
if c.checkAPI {
571-
versions, err := getAPIVersions(c.httpClient, apiEndpoint)
585+
versions, err := c.getAPIVersions(c.httpClient, apiEndpoint)
572586
if err != nil {
573587
return nil, fmt.Errorf("error accessing the API: %w", err)
574588
}
@@ -596,8 +610,8 @@ func versionSupported(n int) bool {
596610
return false
597611
}
598612

599-
func getAPIVersions(httpClient *http.Client, endpoint string) (*versions, error) {
600-
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
613+
func (client *NginxClient) getAPIVersions(httpClient *http.Client, endpoint string) (*versions, error) {
614+
ctx, cancel := context.WithTimeout(context.Background(), client.ctxTimeout)
601615
defer cancel()
602616

603617
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
@@ -852,7 +866,7 @@ func (client *NginxClient) getIDOfHTTPServer(upstream string, name string) (int,
852866
}
853867

854868
func (client *NginxClient) get(path string, data interface{}) error {
855-
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
869+
ctx, cancel := context.WithTimeout(context.Background(), client.ctxTimeout)
856870
defer cancel()
857871

858872
url := fmt.Sprintf("%v/%v/%v", client.apiEndpoint, client.apiVersion, path)
@@ -886,7 +900,7 @@ func (client *NginxClient) get(path string, data interface{}) error {
886900
}
887901

888902
func (client *NginxClient) post(path string, input interface{}) error {
889-
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
903+
ctx, cancel := context.WithTimeout(context.Background(), client.ctxTimeout)
890904
defer cancel()
891905

892906
url := fmt.Sprintf("%v/%v/%v", client.apiEndpoint, client.apiVersion, path)
@@ -918,7 +932,7 @@ func (client *NginxClient) post(path string, input interface{}) error {
918932
}
919933

920934
func (client *NginxClient) delete(path string, expectedStatusCode int) error {
921-
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
935+
ctx, cancel := context.WithTimeout(context.Background(), client.ctxTimeout)
922936
defer cancel()
923937

924938
path = fmt.Sprintf("%v/%v/%v/", client.apiEndpoint, client.apiVersion, path)
@@ -943,7 +957,7 @@ func (client *NginxClient) delete(path string, expectedStatusCode int) error {
943957
}
944958

945959
func (client *NginxClient) patch(path string, input interface{}, expectedStatusCode int) error {
946-
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
960+
ctx, cancel := context.WithTimeout(context.Background(), client.ctxTimeout)
947961
defer cancel()
948962

949963
path = fmt.Sprintf("%v/%v/%v/", client.apiEndpoint, client.apiVersion, path)

client/nginx_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"reflect"
77
"strings"
88
"testing"
9+
"time"
910
)
1011

1112
func TestDetermineUpdates(t *testing.T) {
@@ -578,6 +579,27 @@ func TestClientWithAPIVersion(t *testing.T) {
578579
}
579580
}
580581

582+
func TestClientWithTimeout(t *testing.T) {
583+
t.Parallel()
584+
// Test creating a new client with a supported API version on the client
585+
client, err := NewNginxClient("http://api-url", WithTimeout(1*time.Second))
586+
if err != nil {
587+
t.Fatalf("unexpected error: %v", err)
588+
}
589+
if client == nil {
590+
t.Fatalf("client is nil")
591+
}
592+
593+
// Test creating a new client with an invalid duration
594+
client, err = NewNginxClient("http://api-url", WithTimeout(-1*time.Second))
595+
if err == nil {
596+
t.Fatalf("expected error, but got nil")
597+
}
598+
if client != nil {
599+
t.Fatalf("expected client to be nil, but got %v", client)
600+
}
601+
}
602+
581603
func TestClientWithHTTPClient(t *testing.T) {
582604
t.Parallel()
583605
// Test creating a new client passing a custom HTTP client

0 commit comments

Comments
 (0)