Last active
December 8, 2023 10:29
-
-
Save niksteff/2fd29672a24372782627d99ba2016031 to your computer and use it in GitHub Desktop.
rest v2.10.0 lab
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package resty_test | |
import ( | |
"context" | |
"crypto/tls" | |
"encoding/json" | |
"fmt" | |
"io" | |
"net/http" | |
"net/http/httptest" | |
"testing" | |
"time" | |
"github.com/go-resty/resty/v2" | |
"golang.org/x/net/http2" | |
"golang.org/x/sync/semaphore" | |
) | |
const ( | |
requestCount int = 1000 | |
) | |
type Payload struct { | |
Status int `json:"status"` | |
} | |
func TestConcurrentBuffer(t *testing.T) { | |
var err error | |
// create a response handler | |
mux := http.NewServeMux() | |
mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) { | |
b, err := io.ReadAll(r.Body) | |
if err != nil { | |
w.WriteHeader(http.StatusBadRequest) | |
fmt.Fprintf(w, "error reading request body: %+v", err) | |
return | |
} | |
var payload Payload | |
if err := json.Unmarshal(b, &payload); err != nil { | |
w.WriteHeader(http.StatusBadRequest) | |
fmt.Fprintf(w, "error unmarshaling request body: %+v, body: %s", err, string(b)) | |
return | |
} | |
w.WriteHeader(payload.Status) | |
}) | |
// spin up a test server | |
srv := httptest.NewServer(mux) | |
defer srv.Close() | |
srv.Config.SetKeepAlivesEnabled(true) | |
// configure our http client as our production system | |
// Create a transport | |
transport := http.DefaultTransport.(*http.Transport).Clone() | |
transport.DisableKeepAlives = true | |
transport.MaxIdleConns = 0 | |
// Get a copy of the HTTP2 transport | |
http2Transport, err := http2.ConfigureTransports(transport) | |
if err == nil { | |
// enable healthchecks by setting the idle timeout | |
http2Transport.ReadIdleTimeout = time.Second * 5 // ping is performed at N whenever no frame was received in the meantime | |
// change from the default of 15s | |
http2Transport.PingTimeout = time.Second * 10 // after what time a ping is considered timed out | |
} | |
httpClient := http.Client{ | |
Transport: transport, | |
} | |
// build up a resty client | |
client := resty.NewWithClient(&httpClient) | |
client.SetBaseURL(srv.URL) | |
client.SetRetryCount(3) | |
client.SetRetryWaitTime(5 * time.Millisecond) | |
client.SetRetryMaxWaitTime(25 * time.Millisecond) | |
client.SetTimeout(5 * time.Second) | |
client.Header.Add("Accept", "application/json") | |
client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) | |
client.AddRetryCondition(func(r *resty.Response, err error) bool { | |
// retry for 500, so always we want to provoke retries | |
return err != nil || r.StatusCode() > 499 | |
}) | |
// spawn 1000 concurrent requests | |
sem := semaphore.NewWeighted(100) | |
for i := 0; i < requestCount; i++ { | |
err = sem.Acquire(context.Background(), 1) | |
if err != nil { | |
t.Errorf("could not acquire semaphore: %v", err) | |
return | |
} | |
go func() { | |
defer sem.Release(1) | |
payload := Payload{ | |
Status: http.StatusInternalServerError, | |
} | |
res, err := client.NewRequest().SetBody(payload).Post("/test") | |
if err != nil { | |
t.Errorf("unexpected error: %v", err) | |
} | |
if res.StatusCode() != http.StatusInternalServerError { | |
t.Errorf("unexpected status code %d, expected %d", res.StatusCode(), http.StatusInternalServerError) | |
} | |
if string(res.Body()) != "" { | |
t.Errorf("unexpected body %s, expected empty", string(res.Body())) | |
} | |
// now successful requests | |
payload2 := Payload{ | |
Status: http.StatusOK, | |
} | |
res, err = client.NewRequest().SetBody(payload2).Post("/test") | |
if err != nil { | |
t.Errorf("unexpected error: %v", err) | |
} | |
if res.StatusCode() != http.StatusOK { | |
t.Errorf("unexpected status code %d, expected %d", res.StatusCode(), http.StatusOK) | |
} | |
if string(res.Body()) != "" { | |
t.Errorf("unexpected body %s, expected empty", string(res.Body())) | |
} | |
}() | |
} | |
err = sem.Acquire(context.Background(), 100) | |
if err != nil { | |
t.Errorf("could not wait for all semaphores to finish: %v", err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment