Skip to content

Commit

Permalink
feat: add custom timeout configuration for HTTP client
Browse files Browse the repository at this point in the history
Signed-off-by: Ales Verbic <verbotenj@blinklabs.io>
  • Loading branch information
verbotenj committed Jul 21, 2024
1 parent 481c32c commit 60bd9b7
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 3 deletions.
21 changes: 19 additions & 2 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"strings"
"time"

"github.com/blinklabs-io/cardano-models"
models "github.com/blinklabs-io/cardano-models"
"github.com/blinklabs-io/gouroboros/ledger"
"github.com/fxamacker/cbor/v2"
ginzap "github.com/gin-contrib/zap"
Expand Down Expand Up @@ -113,6 +113,9 @@ func handleSubmitTx(c *gin.Context) {
}
}
}
// Create custom HTTP client
client := createHTTPClient(cfg)

// Send request to each backend
for _, backend := range cfg.Backends {
go func(backend string) {
Expand All @@ -138,7 +141,7 @@ func handleSubmitTx(c *gin.Context) {
return
}
req.Header.Add("Content-Type", "application/cbor")
resp, err := http.DefaultClient.Do(req)
resp, err := client.Do(req)
if err != nil {
logger.Errorf(
"failed to send request to backend %s: %s",
Expand Down Expand Up @@ -175,3 +178,17 @@ func handleSubmitTx(c *gin.Context) {
// Return transaction ID
c.String(202, tx.Hash())
}

// createHTTPClient with custom timeout
func createHTTPClient(cfg *config.Config) *http.Client {
return &http.Client{
Timeout: time.Duration(cfg.Api.ClientTimeout) * time.Millisecond,
Transport: &http.Transport{
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
DisableCompression: false,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}
}
64 changes: 64 additions & 0 deletions api/api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package api

import (
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/blinklabs-io/tx-submit-api-mirror/config"
)

func TestHTTPClientTimeout(t *testing.T) {
client := createHTTPClient(&config.Config{
Api: config.ApiConfig{
ClientTimeout: 100,
},
})

// Create a test server that introduces a delay
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(200 * time.Millisecond) // Delay longer than client timeout
w.WriteHeader(http.StatusOK)
}))
defer testServer.Close()

// Make a request to the test server
resp, err := client.Get(testServer.URL)

// Verify that the request timed out
if err == nil {
t.Errorf("Expected timeout error, but got nil")
}
if resp != nil {
t.Errorf("Expected no response, but got %v", resp)
}
}

func TestHTTPClientTimeoutPass(t *testing.T) {
client := createHTTPClient(&config.Config{
Api: config.ApiConfig{
ClientTimeout: 300,
},
})

// Create a test server that introduces a delay
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(200 * time.Millisecond) // Delay shorter than client timeout
w.WriteHeader(http.StatusOK)
}))
defer testServer.Close()

// Make a request to the test server
resp, err := client.Get(testServer.URL)

// Verify that the request did not time out
if err != nil {
t.Errorf("Expected no error, but got %v", err)
}
if resp == nil {
t.Errorf("Expected response, but got nil")
} else if resp.StatusCode != http.StatusOK {
t.Errorf("Expected status OK, but got %v", resp.StatusCode)
}
}
5 changes: 4 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ package config

import (
"fmt"
"os"

"github.com/kelseyhightower/envconfig"
"gopkg.in/yaml.v2"
"os"
)

type Config struct {
Expand All @@ -34,6 +35,7 @@ type LoggingConfig struct {
type ApiConfig struct {
ListenAddress string `yaml:"address" envconfig:"API_LISTEN_ADDRESS"`
ListenPort uint `yaml:"port" envconfig:"API_LISTEN_PORT"`
ClientTimeout uint `yaml:"client_timeout" envconfig:"CLIENT_TIMEOUT"`
}

// Singleton config instance with default values
Expand All @@ -44,6 +46,7 @@ var globalConfig = &Config{
Api: ApiConfig{
ListenAddress: "",
ListenPort: 8090,
ClientTimeout: 60000, // [ms]
},
}

Expand Down

0 comments on commit 60bd9b7

Please sign in to comment.