all timeouts are customizable #5

This commit is contained in:
Umputun 2021-04-12 21:54:59 -05:00
parent 06a6d595b3
commit 64fd98a130
5 changed files with 68 additions and 21 deletions

View File

@ -98,6 +98,7 @@ Assets server can be used without any proxy providers. In this mode reproxy acts
- `--gzip` enables gizp compression for responses.
- `--max=N` allows to set the maximum size of request (default 64k)
- `--header` sets extra header(s) added to each proxied request
- `--timeout.*` various timeouts for both server and proxy transport. See `timeout` section in [All Application Options](https://github.com/umputun/reproxy#all-application-options)
## Ping and health checks
@ -110,7 +111,6 @@ reproxy provides 2 endpoints for this purpose:
```
-l, --listen= listen on host:port (default: 127.0.0.1:8080) [$LISTEN]
-t, --timeout= proxy timeout (default: 5s) [$TIMEOUT]
-m, --max= max response size (default: 64000) [$MAX_SIZE]
-g, --gzip enable gz compression [$GZIP]
-x, --header= proxy headers [$HEADER]
@ -153,10 +153,20 @@ static:
--static.enabled enable static provider [$STATIC_ENABLED]
--static.rule= routing rules [$STATIC_RULES]
timeout:
--timeout.read-header= read header server timeout (default: 5s) [$TIMEOUT_READ_HEADER]
--timeout.write= write server timeout (default: 30s) [$TIMEOUT_WRITE]
--timeout.idle= idle server timeout (default: 30s) [$TIMEOUT_IDLE]
--timeout.dial= dial transport timeout (default: 30s) [$TIMEOUT_DIAL]
--timeout.keep-alive= keep-alive transport timeout (default: 30s) [$TIMEOUT_KEEP_ALIVE]
--timeout.resp-header= response header transport timeout (default: 5s) [$TIMEOUT_RESP_HEADER]
--timeout.idle-conn= idle connection transport timeout (default: 90s) [$TIMEOUT_IDLE_CONN]
--timeout.tls= TLS hanshake transport timeout (default: 10s) [$TIMEOUT_TLS]
--timeout.continue= expect continue transport timeout (default: 1s) [$TIMEOUT_CONTINUE]
Help Options:
-h, --help Show this help message
```
## Status

View File

@ -24,11 +24,10 @@ import (
)
var opts struct {
Listen string `short:"l" long:"listen" env:"LISTEN" default:"127.0.0.1:8080" description:"listen on host:port"`
TimeOut time.Duration `short:"t" long:"timeout" env:"TIMEOUT" default:"5s" description:"proxy timeout"`
MaxSize int64 `short:"m" long:"max" env:"MAX_SIZE" default:"64000" description:"max response size"`
GzipEnabled bool `short:"g" long:"gzip" env:"GZIP" description:"enable gz compression"`
ProxyHeaders []string `short:"x" long:"header" env:"HEADER" description:"proxy headers" env-delim:","`
Listen string `short:"l" long:"listen" env:"LISTEN" default:"127.0.0.1:8080" description:"listen on host:port"`
MaxSize int64 `short:"m" long:"max" env:"MAX_SIZE" default:"64000" description:"max response size"`
GzipEnabled bool `short:"g" long:"gzip" env:"GZIP" description:"enable gz compression"`
ProxyHeaders []string `short:"x" long:"header" env:"HEADER" description:"proxy headers" env-delim:","`
SSL struct {
Type string `long:"type" env:"TYPE" description:"ssl (auto) support" choice:"none" choice:"static" choice:"auto" default:"none"` //nolint
@ -72,6 +71,18 @@ var opts struct {
Rules []string `long:"rule" env:"RULES" description:"routing rules" env-delim:";"`
} `group:"static" namespace:"static" env-namespace:"STATIC"`
Timeouts struct {
ReadHeader time.Duration `long:"read-header" env:"READ_HEADER" default:"5s" description:"read header server timeout"`
Write time.Duration `long:"write" env:"WRITE" default:"30s" description:"write server timeout"`
Idle time.Duration `long:"idle" env:"IDLE" default:"30s" description:"idle server timeout"`
Dial time.Duration `long:"dial" env:"DIAL" default:"30s" description:"dial transport timeout"`
KeepAlive time.Duration `long:"keep-alive" env:"KEEP_ALIVE" default:"30s" description:"keep-alive transport timeout"`
ResponseHeader time.Duration `long:"resp-header" env:"RESP_HEADER" default:"5s" description:"response header transport timeout"`
IdleConn time.Duration `long:"idle-conn" env:"IDLE_CONN" default:"90s" description:"idle connection transport timeout"`
TLSHandshake time.Duration `long:"tls" env:"TLS" default:"10s" description:"TLS hanshake transport timeout"`
ExpectContinue time.Duration `long:"continue" env:"CONTINUE" default:"1s" description:"expect continue transport timeout"`
} `group:"timeout" namespace:"timeout" env-namespace:"TIMEOUT"`
NoSignature bool `long:"no-signature" env:"NO_SIGNATURE" description:"disable reproxy signature headers"`
Dbg bool `long:"dbg" env:"DEBUG" description:"debug mode"`
}
@ -130,7 +141,6 @@ func main() {
Version: revision,
Matcher: svc,
Address: opts.Listen,
TimeOut: opts.TimeOut,
MaxBodySize: opts.MaxSize,
AssetsLocation: opts.Assets.Location,
AssetsWebRoot: opts.Assets.WebRoot,
@ -139,6 +149,17 @@ func main() {
ProxyHeaders: opts.ProxyHeaders,
AccessLog: accessLog,
DisableSignature: opts.NoSignature,
Timeouts: proxy.Timeouts{
ReadHeader: opts.Timeouts.ReadHeader,
Write: opts.Timeouts.Write,
Idle: opts.Timeouts.Idle,
Dial: opts.Timeouts.Dial,
KeepAlive: opts.Timeouts.KeepAlive,
IdleConn: opts.Timeouts.IdleConn,
TLSHandshake: opts.Timeouts.TLSHandshake,
ExpectContinue: opts.Timeouts.ExpectContinue,
ResponseHeader: opts.Timeouts.ResponseHeader,
},
}
if err := px.Run(context.Background()); err != nil {
log.Fatalf("[ERROR] proxy server failed, %v", err) //nolint gocritic

View File

@ -20,7 +20,7 @@ import (
func TestHttp_healthHandler(t *testing.T) {
port := rand.Intn(10000) + 40000
h := Http{TimeOut: 200 * time.Millisecond, Address: fmt.Sprintf("127.0.0.1:%d", port)}
h := Http{Timeouts: Timeouts{ResponseHeader: 200 * time.Millisecond}, Address: fmt.Sprintf("127.0.0.1:%d", port)}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()

View File

@ -24,7 +24,6 @@ import (
type Http struct { //nolint golint
Matcher
Address string
TimeOut time.Duration
AssetsLocation string
AssetsWebRoot string
MaxBodySize int64
@ -34,6 +33,7 @@ type Http struct { //nolint golint
Version string
AccessLog io.Writer
DisableSignature bool
Timeouts Timeouts
}
// Matcher source info (server and route) to the destination url
@ -44,6 +44,21 @@ type Matcher interface {
Mappers() (mappers []discovery.URLMapper)
}
// Timeouts consolidate timeouts for both server and transport
type Timeouts struct {
// server timeouts
ReadHeader time.Duration
Write time.Duration
Idle time.Duration
// transport timeouts
Dial time.Duration
KeepAlive time.Duration
IdleConn time.Duration
TLSHandshake time.Duration
ExpectContinue time.Duration
ResponseHeader time.Duration
}
// Run the lister and request's router, activate rest server
func (h *Http) Run(ctx context.Context) error {
@ -140,16 +155,16 @@ func (h *Http) proxyHandler() http.HandlerFunc {
h.setXRealIP(r)
},
Transport: &http.Transport{
ResponseHeaderTimeout: h.TimeOut,
ResponseHeaderTimeout: h.Timeouts.ResponseHeader,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
Timeout: h.Timeouts.Dial,
KeepAlive: h.Timeouts.KeepAlive,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
IdleConnTimeout: h.Timeouts.IdleConn,
TLSHandshakeTimeout: h.Timeouts.TLSHandshake,
ExpectContinueTimeout: h.Timeouts.ExpectContinue,
},
}
@ -229,9 +244,9 @@ func (h *Http) makeHTTPServer(addr string, router http.Handler) *http.Server {
return &http.Server{
Addr: addr,
Handler: router,
ReadHeaderTimeout: 5 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 30 * time.Second,
ReadHeaderTimeout: h.Timeouts.ReadHeader,
WriteTimeout: h.Timeouts.Write,
IdleTimeout: h.Timeouts.Idle,
}
}

View File

@ -20,7 +20,8 @@ import (
func TestHttp_Do(t *testing.T) {
port := rand.Intn(10000) + 40000
h := Http{TimeOut: 200 * time.Millisecond, Address: fmt.Sprintf("127.0.0.1:%d", port), AccessLog: io.Discard}
h := Http{Timeouts: Timeouts{ResponseHeader: 200 * time.Millisecond}, Address: fmt.Sprintf("127.0.0.1:%d", port),
AccessLog: io.Discard}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
@ -92,7 +93,7 @@ func TestHttp_Do(t *testing.T) {
func TestHttp_DoWithAssets(t *testing.T) {
port := rand.Intn(10000) + 40000
h := Http{TimeOut: 200 * time.Millisecond, Address: fmt.Sprintf("127.0.0.1:%d", port),
h := Http{Timeouts: Timeouts{ResponseHeader: 200 * time.Millisecond}, Address: fmt.Sprintf("127.0.0.1:%d", port),
AccessLog: io.Discard, AssetsWebRoot: "/static", AssetsLocation: "testdata", DisableSignature: true}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()