Documentation
¶
Overview ¶
Example (NewFailover) ¶
name := "failover-test" f := newFailover(name, nil, nil) fmt.Printf("test: newFailover(nil) -> [enabled:%v] [validate:%v]\n", f.enabled, f.validate()) f = newFailover(name, nil, NewFailoverConfig(failoverFn)) fmt.Printf("test: newFailover(testFn) -> [enabled:%v] [validate:%v]\n", f.enabled, f.validate()) f2 := cloneFailover(f) f2.enabled = true fmt.Printf("test: cloneFailover(f1) -> [f2-enabled:%v] [f2-validate:%v]\n", f2.enabled, f2.validate()) f.enabled = false m := make(map[string]string, 16) failoverState(m, nil) fmt.Printf("test: failoverState(map,nil) -> %v\n", m) m = make(map[string]string, 16) failoverState(m, f) fmt.Printf("test: failoverState(map,f1) -> %v\n", m) m = make(map[string]string, 16) failoverState(m, f2) fmt.Printf("test: failoverState(map,f2) -> %v\n", m)
Output: test: newFailover(nil) -> [enabled:false] [validate:invalid configuration: Failover FailureInvoke function is nil] test: newFailover(testFn) -> [enabled:false] [validate:<nil>] test: cloneFailover(f1) -> [f2-enabled:true] [f2-validate:<nil>] test: failoverState(map,nil) -> map[failover:] test: failoverState(map,f1) -> map[failover:false] test: failoverState(map,f2) -> map[failover:true]
Example (NewProxy) ¶
t := newTable(true, false) p := newProxy("test-route", t, NewProxyConfig(false, "http://localhost:8080", []Header{{"name", "value"}, {"name2", "value2"}})) fmt.Printf("test: newProxy() -> [name:%v] [current:%v] [headers:%v]\n", p.name, p.pattern, p.headers) p = newProxy("test-route2", t, NewProxyConfig(false, "https://google.com", nil)) fmt.Printf("test: newProxy() -> [name:%v] [current:%v]\n", p.name, p.pattern) p2 := cloneProxy(p) p2.pattern = "urn:test" fmt.Printf("test: cloneProxy() -> [prev-config:%v] [prev-name:%v] [curr-config:%v] [curr-name:%v]\n", p.pattern, p.name, p2.pattern, p2.name)
Output: test: newProxy() -> [name:test-route] [current:http://localhost:8080] [headers:[{name value} {name2 value2}]] test: newProxy() -> [name:test-route2] [current:https://google.com] test: cloneProxy() -> [prev-config:https://google.com] [prev-name:test-route2] [curr-config:urn:test] [curr-name:test-route2]
Example (NewRateLimiter) ¶
t := newRateLimiter("test-route", newTable(true, false), NewRateLimiterConfig(1, 100, 503)) limit, burst := t.LimitAndBurst() fmt.Printf("test: newRateLimiter() -> [name:%v] [limit:%v] [burst:%v] [statusCode:%v]\n", t.name, limit, burst, t.StatusCode()) t = newRateLimiter("test-route2", newTable(true, false), NewRateLimiterConfig(rate.Inf, DefaultBurst, 429)) limit, burst = t.LimitAndBurst() fmt.Printf("test: newRateLimiter() -> [name:%v] [limit:%v] [burst:%v] [statusCode:%v]\n", t.name, limit, burst, t.StatusCode()) t2 := cloneRateLimiter(t) t2.config.Limit = 123 fmt.Printf("test: cloneRateLimiter() -> [prev-limit:%v] [prev-name:%v] [curr-limit:%v] [curr-name:%v]\n", t.config.Limit, t.name, t2.config.Limit, t2.name)
Output: test: newRateLimiter() -> [name:test-route] [limit:1] [burst:100] [statusCode:503] test: newRateLimiter() -> [name:test-route2] [limit:1.7976931348623157e+308] [burst:1] [statusCode:429] test: cloneRateLimiter() -> [prev-limit:1.7976931348623157e+308] [prev-name:test-route2] [curr-limit:123] [curr-name:test-route2]
Example (NewRetry) ¶
t := newRetry("test-route", newTable(true, false), NewRetryConfig([]int{504}, 5, 10, 0)) limit, burst := t.LimitAndBurst() fmt.Printf("test: newRetry() -> [name:%v] [config:%v] [limit:%v] [burst:%v]\n", t.name, t.config, limit, burst) t = newRetry("test-route2", newTable(true, false), NewRetryConfig([]int{503, 504}, 2, 20, 0)) fmt.Printf("test: newRetry() -> [name:%v] [config:%v]\n", t.name, t.config) t2 := cloneRetry(t) t2.enabled = false fmt.Printf("test: cloneRetry() -> [prev-enabled:%v] [curr-enabled:%v]\n", t.enabled, t2.enabled) //t = newRetry("test-route3", newTable(true), NewRetryConfig([]int{503, 504}, time.Millisecond*2000, false)) fmt.Printf("test: retryState(nil,false,map) -> %v\n", retryState(nil, nil, false)) fmt.Printf("test: retryState(t,false,map) -> %v\n", retryState(nil, t, false)) t2 = newRetry("test-route", newTable(true, false), NewRetryConfig([]int{504}, rate.Inf, 10, 0)) fmt.Printf("test: retryState(t2,true,map) -> %v\n", retryState(nil, t2, true))
Output: test: newRetry() -> [name:test-route] [config:{5 10 0s [504]}] [limit:5] [burst:10] test: newRetry() -> [name:test-route2] [config:{2 20 0s [503 504]}] test: cloneRetry() -> [prev-enabled:true] [curr-enabled:false] test: retryState(nil,false,map) -> map[retry: retryBurst:-1 retryRateLimit:-1] test: retryState(t,false,map) -> map[retry:false retryBurst:20 retryRateLimit:2] test: retryState(t2,true,map) -> map[retry:true retryBurst:10 retryRateLimit:99999]
Example (NewTimeout) ¶
t := newTimeout("test-route", newTable(true, false), NewTimeoutConfig(100, 0)) fmt.Printf("test: newTimeout() -> [name:%v] [current:%v]\n", t.name, t.config.Duration) t = newTimeout("test-route2", newTable(true, false), NewTimeoutConfig(time.Millisecond*2000, 503)) fmt.Printf("test: newTimeout() -> [name:%v] [current:%v]\n", t.name, t.config.Duration) t2 := cloneTimeout(t) t2.config.Duration = time.Millisecond * 1000 fmt.Printf("test: cloneTimeout() -> [prev-config:%v] [prev-name:%v] [curr-config:%v] [curr-name:%v]\n", t.config, t.name, t2.config, t2.name)
Output: test: newTimeout() -> [name:test-route] [current:100ns] test: newTimeout() -> [name:test-route2] [current:2s] test: cloneTimeout() -> [prev-config:{2s 503}] [prev-name:test-route2] [curr-config:{1s 503}] [curr-name:test-route2]
Index ¶
- Constants
- func ConvertDuration(s string) (time.Duration, error)
- func EgressApply(ctx context.Context, statusCode func() int, uri, requestId, method string) (func(), context.Context, bool)
- func ExtractState(state, name string) string
- func FmtLog(traffic string, start time.Time, duration time.Duration, req *http.Request, ...) string
- func FmtTimestamp(t time.Time) string
- func InitEgressControllers(read func() ([]byte, error), update func(routes []Route) error) []error
- func InitIngressControllers(read func() ([]byte, error), update func(routes []Route) error) []error
- func IsEmpty(s string) bool
- func ParseState(s string) (names []string, values []string)
- func ParseUri(uri string) (scheme, host, path string)
- func SetLogFn(fn Log)
- func Trim(s string) string
- type Configuration
- type Controller
- type Controllers
- type Failover
- type FailoverConfig
- type FailoverInvoke
- type Header
- type HttpMatcher
- type Log
- type Proxy
- type ProxyConfig
- type RateLimiter
- type RateLimiterConfig
- type Retry
- type RetryConfig
- type RetryConfigJson
- type Route
- type RouteConfig
- type Table
- type Timeout
- type TimeoutConfig
- type TimeoutConfigJson
- type UriMatcher
Examples ¶
Constants ¶
const ( StatusDeadlineExceeded = 4 StatusRateLimited = 94 )
const ( RateLimitInfValue = 99999 HostControllerName = "host" DefaultControllerName = "*" NilControllerName = "!" FromRouteHeaderName = "from-route" RateLimitFlag = "RL" UpstreamTimeoutFlag = "UT" HostTimeoutFlag = "HT" NotEnabledFlag = "NE" )
const ( DefaultIngressRouteName = "default-ingress" DefaultEgressRouteName = "default-egress" )
const ( InfValue = "-1" DefaultBurst = 1 )
const ( EgressTraffic = "egress" IngressTraffic = "ingress" PingTraffic = "ping" PingName = "ping" TimeoutName = "timeout" FailoverName = "failover" ProxyName = "proxy" RetryName = "retry" RetryRateLimitName = "retryRateLimit" RetryRateBurstName = "retryBurst" RateLimitName = "rateLimit" RateBurstName = "burst" ControllerName = "name" RequestIdHeaderName = "X-REQUEST-ID" )
Variables ¶
This section is empty.
Functions ¶
func ConvertDuration ¶
Example ¶
s := "" duration, err := ConvertDuration(s) fmt.Printf("test: ConvertDuration(\"%v\") [err:%v] [duration:%v]\n", s, err, duration) s = " " duration, err = ConvertDuration(s) fmt.Printf("test: ConvertDuration(\"%v\") [err:%v] [duration:%v]\n", s, err, duration) s = "12as" duration, err = ConvertDuration(s) fmt.Printf("test: ConvertDuration(\"%v\") [err:%v] [duration:%v]\n", s, err, duration) s = "1000" duration, err = ConvertDuration(s) fmt.Printf("test: ConvertDuration(\"%v\") [err:%v] [duration:%v]\n", s, err, duration) s = "1000s" duration, err = ConvertDuration(s) fmt.Printf("test: ConvertDuration(\"%v\") [err:%v] [duration:%v]\n", s, err, duration) s = "1000m" duration, err = ConvertDuration(s) fmt.Printf("test: ConvertDuration(\"%v\") [err:%v] [duration:%v]\n", s, err, duration) s = "1m" duration, err = ConvertDuration(s) fmt.Printf("test: ConvertDuration(\"%v\") [err:%v] [duration:%v]\n", s, err, duration) s = "10ms" duration, err = ConvertDuration(s) fmt.Printf("test: ConvertDuration(\"%v\") [err:%v] [duration:%v]\n", s, err, duration) //t := time.Microsecond * 100 //fmt.Printf("test: time.String %v\n", t.String()) s = "10µs" duration, err = ConvertDuration(s) fmt.Printf("test: ConvertDuration(\"%v\") [err:%v] [duration:%v]\n", s, err, duration)
Output: test: ConvertDuration("") [err:<nil>] [duration:0s] test: ConvertDuration(" ") [err:strconv.Atoi: parsing " ": invalid syntax] [duration:0s] test: ConvertDuration("12as") [err:strconv.Atoi: parsing "12a": invalid syntax] [duration:0s] test: ConvertDuration("1000") [err:<nil>] [duration:16m40s] test: ConvertDuration("1000s") [err:<nil>] [duration:16m40s] test: ConvertDuration("1000m") [err:<nil>] [duration:16h40m0s] test: ConvertDuration("1m") [err:<nil>] [duration:1m0s] test: ConvertDuration("10ms") [err:<nil>] [duration:10ms] test: ConvertDuration("10µs") [err:<nil>] [duration:10µs]
func EgressApply ¶
func EgressApply(ctx context.Context, statusCode func() int, uri, requestId, method string) (func(), context.Context, bool)
EgressApply - function to be used by non Http egress traffic to apply an controller
Example ¶
function(context.Background())
Output: {traffic:egress ,route:* ,request-id:123-456-7890, status-code:0, method:GET, url:urn:postgres:query.access-log, host:postgres, path:query.access-log, timeout:-1, rate-limit:-1, rate-burst:-1, retry:, retry-rate-limit:-1, retry-rate-burst:-1, status-flags:}
func ExtractState ¶
func FmtTimestamp ¶
func InitEgressControllers ¶
func InitIngressControllers ¶
func ParseState ¶
Types ¶
type Configuration ¶
type Configuration interface { SetHttpMatcher(fn HttpMatcher) SetUriMatcher(fn UriMatcher) SetDefaultController(route Route) []error SetHostController(route Route) []error AddController(route Route) []error }
Configuration - configuration for actuators
type Controller ¶
type Controller interface { Name() string Timeout() (Timeout, bool) RateLimiter() (RateLimiter, bool) Retry() (Retry, bool) Failover() (Failover, bool) Proxy() (Proxy, bool) UpdateHeaders(req *http.Request) LogHttpIngress(start time.Time, duration time.Duration, req *http.Request, statusCode int, written int64, statusFlags string) LogHttpEgress(start time.Time, duration time.Duration, req *http.Request, resp *http.Response, statusFlags string, retry bool) LogEgress(start time.Time, duration time.Duration, statusCode int, uri, requestId, method, statusFlags string) // contains filtered or unexported methods }
Controller - definition for properties of a controller
Example (NewController) ¶
t := newTable(true, false) route := NewRoute("test", EgressTraffic, "", false, NewTimeoutConfig(time.Millisecond*1500, 0), NewRateLimiterConfig(100, 10, 503)) ctrl, _ := newController(route, t) _, toOk := ctrl.Timeout() _, rateOk := ctrl.RateLimiter() _, retryOk := ctrl.Retry() _, failOk := ctrl.Failover() fmt.Printf("test: newController() -> [timeout:%v] [rateLimit:%v] [retry:%v] [failover:%v]\n", toOk, rateOk, retryOk, failOk) d := ctrl.timeout.Duration() a1 := cloneController[*timeout](ctrl, newTimeout("new-timeout", t, NewTimeoutConfig(time.Millisecond*500, http.StatusGatewayTimeout))) d1 := a1.timeout.Duration() fmt.Printf("test: cloneController() -> [prev-duration:%v] [curr-duration:%v]\n", d, d1)
Output: test: newController() -> [timeout:true] [rateLimit:true] [retry:false] [failover:false] test: cloneController() -> [prev-duration:1.5s] [curr-duration:500ms]
Example (NewController_Error) ¶
t := newTable(false, false) route := NewRoute("test", IngressTraffic, "", false, NewTimeoutConfig(time.Millisecond*1500, 0), NewRateLimiterConfig(100, 10, 503)) _, errs := newController(route, t) fmt.Printf("test: newController() -> [errs:%v]\n", errs) route = NewRoute("test", IngressTraffic, "", false, NewTimeoutConfig(time.Millisecond*1500, 0), NewRetryConfig(nil, 100, 10, 0)) _, errs = newController(route, t) fmt.Printf("test: newController() -> [errs:%v]\n", errs) route = NewRoute("test", IngressTraffic, "", false, NewTimeoutConfig(0, 0)) _, errs = newController(route, t) fmt.Printf("test: newController() -> [errs:%v]\n", errs) route = NewRoute("test", IngressTraffic, "", false, NewTimeoutConfig(10, 0), NewFailoverConfig(nil)) _, errs = newController(route, t) fmt.Printf("test: newController() -> [errs:%v]\n", errs) route = newRoute("test", NewRateLimiterConfig(-1, 10, 504)) _, errs = newController(route, t) fmt.Printf("test: newController() -> [errs:%v]\n", errs)
Output: test: newController() -> [errs:[]] test: newController() -> [errs:[invalid configuration: Retry status codes are empty]] test: newController() -> [errs:[invalid configuration: Timeout duration is <= 0]] test: newController() -> [errs:[invalid configuration: Failover FailureInvoke function is nil]] test: newController() -> [errs:[invalid configuration: RateLimiter limit is < 0]]
Example (NewController_config) ¶
t := newTable(true, false) route := NewRoute("test", EgressTraffic, "", false, NewTimeoutConfig(time.Millisecond*1500, 0), nil, NewRateLimiterConfig(100, 10, 503), nil) ctrl, _ := newController(route, t) _, toOk := ctrl.Timeout() _, rateOk := ctrl.RateLimiter() _, retryOk := ctrl.Retry() _, failOk := ctrl.Failover() fmt.Printf("test: newController() -> [timeout:%v] [rateLimit:%v] [retry:%v] [failover:%v]\n", toOk, rateOk, retryOk, failOk) //d := ctrl.timeout.Duration() //ctrl1 := cloneController[*timeout](ctrl, newTimeout("new-timeout", t, NewTimeoutConfig(time.Millisecond*500, http.StatusGatewayTimeout))) //d1 := ctrl1.timeout.Duration() //fmt.Printf("test: cloneController() -> [prev-duration:%v] [curr-duration:%v]\n", d, d1) //ctrl.Actuate(nil)
Output: test: newController() -> [timeout:true] [rateLimit:true] [retry:false] [failover:false]
type Controllers ¶
type Controllers interface { Host() Controller Default() Controller LookupHttp(req *http.Request) Controller LookupUri(urn string, method string) Controller LookupByName(name string) Controller }
Controllers - public interface
type FailoverConfig ¶
type FailoverConfig struct { Enabled bool // contains filtered or unexported fields }
func NewFailoverConfig ¶
func NewFailoverConfig(invoke FailoverInvoke) *FailoverConfig
type FailoverInvoke ¶
type HttpMatcher ¶
HttpMatcher - type for Ingress/Egress table lookups by request
type Log ¶
type Log func(traffic string, start time.Time, duration time.Duration, req *http.Request, resp *http.Response, statusFlags string, controllerState map[string]string)
Log - type for logging
type Proxy ¶
type Proxy interface { IsEnabled() bool Enable() Disable() Pattern() string SetPattern(pattern string) Headers() []Header BuildUrl(uri *url.URL) *url.URL }
Proxy - interface for proxy
type ProxyConfig ¶
func NewProxyConfig ¶
func NewProxyConfig(enabled bool, pattern string, headers []Header) *ProxyConfig
type RateLimiter ¶
type RateLimiter interface { Allow() bool StatusCode() int SetLimit(limit rate.Limit) SetBurst(burst int) SetRateLimiter(limit rate.Limit, burst int) AdjustRateLimiter(percentage int) bool LimitAndBurst() (rate.Limit, int) }
RateLimiter - interface for rate limiting
type RateLimiterConfig ¶
func NewRateLimiterConfig ¶
func NewRateLimiterConfig(limit rate.Limit, burst int, statusCode int) *RateLimiterConfig
type Retry ¶
type Retry interface { IsEnabled() bool Enable() Disable() IsRetryable(statusCode int) (ok bool, status string) SetRateLimiter(limit rate.Limit, burst int) AdjustRateLimiter(percentage int) bool LimitAndBurst() (rate.Limit, int) }
Retry - interface for retries
type RetryConfig ¶
func NewRetryConfig ¶
type RetryConfigJson ¶
type Route ¶
type Route struct { Name string Pattern string Traffic string // egress/ingress Ping bool // health traffic Protocol string // gRPC, HTTP10, HTTP11, HTTP2, HTTP3gRPC, HTTP Timeout *TimeoutConfig RateLimiter *RateLimiterConfig Retry *RetryConfig Failover *FailoverConfig Proxy *ProxyConfig }
Route - route data
func AddEgressRoutes ¶
AddEgressRoutes - read the routes from the []byte and create the EgressTable controller entries
func AddIngressRoutes ¶
AddIngressRoutes - read the routes from the []byte and create the IngressTable controller entries
func NewRoute ¶
NewRoute - creates a new route
Example ¶
name := "nil-config" route := newRoute(name) fmt.Printf("test: newRoute() -> [name:%v] [timeout:%v] [rateLimiter:%v] [retry:%v] [failover:%v]\n", name, route.Timeout != nil, route.RateLimiter != nil, route.Retry != nil, route.Failover != nil) name = "timeout" route = newRoute(name, NewTimeoutConfig(time.Second*2, 504)) fmt.Printf("test: newRoute() -> [name:%v] [timeout:%v] [rateLimiter:%v] [retry:%v] [failover:%v]\n", name, route.Timeout != nil, route.RateLimiter != nil, route.Retry != nil, route.Failover != nil) name = "timeout-rateLimiter" route = newRoute(name, NewTimeoutConfig(time.Second*2, 504), NewRateLimiterConfig(100, 25, 503)) fmt.Printf("test: newRoute() -> [name:%v] [timeout:%v] [rateLimiter:%v] [retry:%v] [failover:%v]\n", name, route.Timeout != nil, route.RateLimiter != nil, route.Retry != nil, route.Failover != nil) name = "timeout-rateLimiter-retry" route = newRoute(name, NewTimeoutConfig(time.Second*2, 504), NewRateLimiterConfig(100, 25, 503), NewRetryConfig([]int{504, 503}, 100, 25, time.Second)) fmt.Printf("test: newRoute() -> [name:%v] [timeout:%v] [rateLimiter:%v] [retry:%v] [failover:%v]\n", name, route.Timeout != nil, route.RateLimiter != nil, route.Retry != nil, route.Failover != nil) name = "timeout-rateLimiter-retry-failover" route = newRoute(name, NewTimeoutConfig(time.Second*2, 504), NewRateLimiterConfig(100, 25, 503), NewRetryConfig([]int{504, 503}, 100, 25, time.Second), NewFailoverConfig(nil)) fmt.Printf("test: newRoute() -> [name:%v] [timeout:%v] [rateLimiter:%v] [retry:%v] [failover:%v]\n", name, route.Timeout != nil, route.RateLimiter != nil, route.Retry != nil, route.Failover != nil) name = "timeout-rateLimiter-nil" route = newRoute(name, nil, NewTimeoutConfig(time.Second*2, 504), nil, NewRateLimiterConfig(100, 25, 503), nil) fmt.Printf("test: newRoute() -> [name:%v] [timeout:%v] [rateLimiter:%v] [retry:%v] [failover:%v]\n", name, route.Timeout != nil, route.RateLimiter != nil, route.Retry != nil, route.Failover != nil)
Output: test: newRoute() -> [name:nil-config] [timeout:false] [rateLimiter:false] [retry:false] [failover:false] test: newRoute() -> [name:timeout] [timeout:true] [rateLimiter:false] [retry:false] [failover:false] test: newRoute() -> [name:timeout-rateLimiter] [timeout:true] [rateLimiter:true] [retry:false] [failover:false] test: newRoute() -> [name:timeout-rateLimiter-retry] [timeout:true] [rateLimiter:true] [retry:true] [failover:false] test: newRoute() -> [name:timeout-rateLimiter-retry-failover] [timeout:true] [rateLimiter:true] [retry:true] [failover:true] test: newRoute() -> [name:timeout-rateLimiter-nil] [timeout:true] [rateLimiter:true] [retry:false] [failover:false]
func NewRouteFromConfig ¶
func NewRouteFromConfig(config RouteConfig) (Route, error)
NewRouteFromConfig - creates a new route from configuration
Example ¶
config := RouteConfig{ Name: "test-route", Pattern: "/health/liveness", Timeout: &TimeoutConfigJson{ Duration: "500ms", StatusCode: 5040, }, RateLimiter: nil, Retry: &RetryConfigJson{ Limit: 100, Burst: 25, Wait: "5x", Codes: nil, }, Failover: nil, } route, err := NewRouteFromConfig(config) fmt.Printf("test: NewRouteFromConfig() [err:%v] [route:%v]\n", err, route) config.Retry.Wait = "245s" route, err = NewRouteFromConfig(config) fmt.Printf("test: NewRouteFromConfig() [err:%v] [timeout:%v] [retry:%v]\n", err, route.Timeout, route.Retry) config.Timeout.Duration = "x34" route, err = NewRouteFromConfig(config) fmt.Printf("test: NewRouteFromConfig() [err:%v] [route:%v]\n", err, route)
Output: test: NewRouteFromConfig() [err:strconv.Atoi: parsing "5x": invalid syntax] [route:{ false <nil> <nil> <nil> <nil> <nil>}] test: NewRouteFromConfig() [err:<nil>] [timeout:&{500ms 5040}] [retry:&{100 25 4m5s []}] test: NewRouteFromConfig() [err:strconv.Atoi: parsing "x34": invalid syntax] [route:{ false <nil> <nil> <nil> <nil> <nil>}]
func ReadRoutes ¶
ReadRoutes - read routes from the []byte representation of a route configuration
func (Route) IsConfigured ¶
type RouteConfig ¶
type RouteConfig struct { Name string Pattern string Traffic string // Egress/Ingress Ping bool // Health traffic Protocol string // gRPC, HTTP10, HTTP11, HTTP2, HTTP3 Timeout *TimeoutConfigJson RateLimiter *RateLimiterConfig Retry *RetryConfigJson Failover *FailoverConfig Proxy *ProxyConfig }
type Table ¶
type Table interface { Configuration Controllers }
Table - controller table
func EgressTable ¶
func EgressTable() Table
func IngressTable ¶
func IngressTable() Table
type Timeout ¶
type Timeout interface { Duration() time.Duration SetTimeout(timeout time.Duration) StatusCode() int }
Timeout - interface for timeouts
type TimeoutConfig ¶
func NewTimeoutConfig ¶
func NewTimeoutConfig(duration time.Duration, statusCode int) *TimeoutConfig