diff --git a/config/runtime/handler.go b/config/runtime/handler.go index 23c088238..b0b7ef189 100644 --- a/config/runtime/handler.go +++ b/config/runtime/handler.go @@ -9,9 +9,7 @@ import ( "path" "strconv" "strings" - "time" - "github.com/docker/go-units" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/gohcl" "github.com/sirupsen/logrus" @@ -64,24 +62,12 @@ func BuildEntrypointHandlers(conf *config.Gateway, httpConf *HTTPConfig, log *lo } beConf, _ = defaultBackendConf.Merge(beConf) - - bodyLimit, err := units.FromHumanSize(beConf.RequestBodyLimit) + proxyOptions, err := handler.NewProxyOptions(beConf, nil, []hcl.Body{beConf.Options}) if err != nil { - log.Fatalf("backend bodyLimit: %v", err) + log.Fatal(err) } - t, ttfbt, ct := parseBackendTimings(beConf) - proxy, err := handler.NewProxy(&handler.ProxyOptions{ - RequestBodyLimit: bodyLimit, - BackendName: beConf.Name, - ConnectTimeout: ct, - Context: []hcl.Body{beConf.Options}, - Hostname: beConf.Hostname, - Origin: beConf.Origin, - Path: beConf.Path, - Timeout: t, - TTFBTimeout: ttfbt, - }, log, conf.Context) + proxy, err := handler.NewProxy(proxyOptions, log, conf.Context) if err != nil { log.Fatal(err) } @@ -180,29 +166,17 @@ func BuildEntrypointHandlers(conf *config.Gateway, httpConf *HTTPConfig, log *lo if endpoint.Path != "" { beConf, remainCtx := protectedBackend.conf.Merge(&config.Backend{Path: endpoint.Path}) - t, ttfbt, ct := parseBackendTimings(beConf) - - bodyLimit, err := units.FromHumanSize(beConf.RequestBodyLimit) + corsOptions, err := handler.NewCORSOptions(server.API.CORS) if err != nil { - log.Fatalf("backend bodyLimit: %v", err) + log.Fatal(err) } - corsOptions, err := handler.NewCORSOptions(server.API.CORS) + proxyOptions, err := handler.NewProxyOptions(beConf, corsOptions, remainCtx) if err != nil { log.Fatal(err) } - proxy, err := handler.NewProxy(&handler.ProxyOptions{ - BackendName: beConf.Name, - CORS: corsOptions, - ConnectTimeout: ct, - Context: remainCtx, - Hostname: beConf.Hostname, - Origin: beConf.Origin, - Path: beConf.Path, - RequestBodyLimit: bodyLimit, - TTFBTimeout: ttfbt, - Timeout: t, - }, log, conf.Context) + + proxy, err := handler.NewProxy(proxyOptions, log, conf.Context) if err != nil { log.Fatal(err) } @@ -256,29 +230,18 @@ func BuildEntrypointHandlers(conf *config.Gateway, httpConf *HTTPConfig, log *lo } beConf, remainCtx := backends[inlineConf.Name].conf.Merge(inlineConf) - t, ttfbt, ct := parseBackendTimings(beConf) - bodyLimit, err := units.FromHumanSize(beConf.RequestBodyLimit) + corsOptions, err := handler.NewCORSOptions(server.API.CORS) if err != nil { - log.Fatalf("backend bodyLimit: %v", err) + log.Fatal(err) } - corsOptions, err := handler.NewCORSOptions(server.API.CORS) + proxyOptions, err := handler.NewProxyOptions(beConf, corsOptions, remainCtx) if err != nil { log.Fatal(err) } - proxy, err := handler.NewProxy(&handler.ProxyOptions{ - BackendName: beConf.Name, - CORS: corsOptions, - ConnectTimeout: ct, - Context: remainCtx, - Hostname: beConf.Hostname, - Origin: beConf.Origin, - Path: beConf.Path, - RequestBodyLimit: bodyLimit, - TTFBTimeout: ttfbt, - Timeout: t, - }, log, conf.Context) + + proxy, err := handler.NewProxy(proxyOptions, log, conf.Context) if err != nil { log.Fatal(err) } @@ -482,51 +445,20 @@ func newInlineBackend(evalCtx *hcl.EvalContext, inlineDef hcl.Body, cors *config beConf, _ = defaultBackendConf.Merge(beConf) - t, ttfbt, ct := parseBackendTimings(beConf) - - bodyLimit, err := units.FromHumanSize(beConf.RequestBodyLimit) + corsOptions, err := handler.NewCORSOptions(cors) if err != nil { - log.Fatalf("backend bodyLimit: %v", err) + return nil, nil, err } - corsOptions, err := handler.NewCORSOptions(cors) + proxyOptions, err := handler.NewProxyOptions(beConf, corsOptions, []hcl.Body{beConf.Options}) if err != nil { return nil, nil, err } - proxy, err := handler.NewProxy(&handler.ProxyOptions{ - BackendName: beConf.Name, - CORS: corsOptions, - ConnectTimeout: ct, - Context: []hcl.Body{beConf.Options}, - Hostname: beConf.Hostname, - Origin: beConf.Origin, - Path: beConf.Path, - RequestBodyLimit: bodyLimit, - TTFBTimeout: ttfbt, - Timeout: t, - }, log, evalCtx) + proxy, err := handler.NewProxy(proxyOptions, log, evalCtx) return proxy, beConf, err } -func parseBackendTimings(conf *config.Backend) (time.Duration, time.Duration, time.Duration) { - c, _ := defaultBackendConf.Merge(conf) - - totalD, err := time.ParseDuration(c.Timeout) - if err != nil { - panic(err) - } - ttfbD, err := time.ParseDuration(c.TTFBTimeout) - if err != nil { - panic(err) - } - connectD, err := time.ParseDuration(c.ConnectTimeout) - if err != nil { - panic(err) - } - return totalD, ttfbD, connectD -} - func getAbsPath(file string, log *logrus.Entry) string { if strings.HasPrefix(file, "/") { return file diff --git a/handler/proxy.go b/handler/proxy.go index b9878dd31..115a955e8 100644 --- a/handler/proxy.go +++ b/handler/proxy.go @@ -50,61 +50,12 @@ type Proxy struct { upstreamLog *logging.AccessLog } -type ProxyOptions struct { - ConnectTimeout, Timeout, TTFBTimeout time.Duration - Context []hcl.Body - BackendName string - Hostname, Origin, Path string - CORS *CORSOptions - RequestBodyLimit int64 -} - type CORSOptions struct { AllowedOrigins []string AllowCredentials bool MaxAge string } -func (po *ProxyOptions) Merge(o *ProxyOptions) *ProxyOptions { - if o.ConnectTimeout > 0 { - po.ConnectTimeout = o.ConnectTimeout - } - - if o.Timeout > 0 { - po.Timeout = o.ConnectTimeout - } - - if o.TTFBTimeout > 0 { - po.TTFBTimeout = o.TTFBTimeout - } - - if len(o.Context) > 0 { - po.Context = append(po.Context, o.Context...) - } - - if o.CORS != nil { - po.CORS = o.CORS - } - - if o.Hostname != "" { - po.Hostname = o.Hostname - } - - if o.Origin != "" { - po.Origin = o.Origin - } - - if o.Path != "" { - po.Path = o.Path - } - - if o.RequestBodyLimit != po.RequestBodyLimit { - po.RequestBodyLimit = o.RequestBodyLimit - } - - return po -} - func NewCORSOptions(cors *config.CORS) (*CORSOptions, error) { if cors == nil { return nil, nil diff --git a/handler/proxy_options.go b/handler/proxy_options.go new file mode 100644 index 000000000..7c3db55cf --- /dev/null +++ b/handler/proxy_options.go @@ -0,0 +1,98 @@ +package handler + +import ( + "fmt" + "time" + + "github.com/docker/go-units" + "github.com/hashicorp/hcl/v2" + + "github.com/avenga/couper/config" +) + +type ProxyOptions struct { + ConnectTimeout, Timeout, TTFBTimeout time.Duration + Context []hcl.Body + BackendName string + Hostname, Origin, Path string + CORS *CORSOptions + RequestBodyLimit int64 +} + +func NewProxyOptions(conf *config.Backend, corsOpts *CORSOptions, remainCtx []hcl.Body) (*ProxyOptions, error) { + totalD, err := time.ParseDuration(conf.Timeout) + if err != nil { + panic(err) + } + ttfbD, err := time.ParseDuration(conf.TTFBTimeout) + if err != nil { + panic(err) + } + connectD, err := time.ParseDuration(conf.ConnectTimeout) + if err != nil { + panic(err) + } + + bodyLimit, err := units.FromHumanSize(conf.RequestBodyLimit) + if err != nil { + return nil, fmt.Errorf("backend bodyLimit: %v", err) + } + + cors := corsOpts + if cors == nil { // Could be nil on non api context like 'free' endpoints or definitions. + cors = &CORSOptions{} + } + + return &ProxyOptions{ + BackendName: conf.Name, + CORS: cors, + ConnectTimeout: connectD, + Context: remainCtx, + Hostname: conf.Hostname, + Origin: conf.Origin, + Path: conf.Path, + RequestBodyLimit: bodyLimit, + TTFBTimeout: ttfbD, + Timeout: totalD, + }, nil +} + +func (po *ProxyOptions) Merge(o *ProxyOptions) *ProxyOptions { + if o.ConnectTimeout > 0 { + po.ConnectTimeout = o.ConnectTimeout + } + + if o.Timeout > 0 { + po.Timeout = o.ConnectTimeout + } + + if o.TTFBTimeout > 0 { + po.TTFBTimeout = o.TTFBTimeout + } + + if len(o.Context) > 0 { + po.Context = append(po.Context, o.Context...) + } + + if o.CORS != nil { + po.CORS = o.CORS + } + + if o.Hostname != "" { + po.Hostname = o.Hostname + } + + if o.Origin != "" { + po.Origin = o.Origin + } + + if o.Path != "" { + po.Path = o.Path + } + + if o.RequestBodyLimit != po.RequestBodyLimit { + po.RequestBodyLimit = o.RequestBodyLimit + } + + return po +}