From 3b0c523e49cc70812fdec38dd547bc8ce474de7c Mon Sep 17 00:00:00 2001 From: "E. Stuart Hicks" Date: Mon, 8 Jul 2019 14:32:00 -0400 Subject: [PATCH] added proxy-http-version annotation to override the HTTP/1.1 default connection type to reverse proxy backends --- .../user-guide/nginx-configuration/annotations.md | 10 ++++++++++ internal/ingress/annotations/proxy/main.go | 9 +++++++++ internal/ingress/annotations/proxy/main_test.go | 8 ++++++++ internal/ingress/controller/config/config.go | 5 +++++ internal/ingress/controller/controller.go | 1 + internal/ingress/defaults/main.go | 4 ++++ rootfs/etc/nginx/template/nginx.tmpl | 5 ++--- test/e2e/annotations/proxy.go | 15 +++++++++++++++ 8 files changed, 54 insertions(+), 3 deletions(-) diff --git a/docs/user-guide/nginx-configuration/annotations.md b/docs/user-guide/nginx-configuration/annotations.md index 824b0512a5..cdd696b144 100755 --- a/docs/user-guide/nginx-configuration/annotations.md +++ b/docs/user-guide/nginx-configuration/annotations.md @@ -64,6 +64,7 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz |[nginx.ingress.kubernetes.io/proxy-request-buffering](#custom-timeouts)|string| |[nginx.ingress.kubernetes.io/proxy-redirect-from](#proxy-redirect)|string| |[nginx.ingress.kubernetes.io/proxy-redirect-to](#proxy-redirect)|string| +|[nginx.ingress.kubernetes.io/proxy-http-version](#proxy-http-version)|"1.0" or "1.1"| |[nginx.ingress.kubernetes.io/enable-rewrite-log](#enable-rewrite-log)|"true" or "false"| |[nginx.ingress.kubernetes.io/rewrite-target](#rewrite)|URI| |[nginx.ingress.kubernetes.io/satisfy](#satisfy)|string| @@ -569,6 +570,15 @@ To configure this setting globally, set `proxy-buffer-size` in [NGINX ConfigMap] nginx.ingress.kubernetes.io/proxy-buffer-size: "8k" ``` +### Proxy HTTP version + +Using this annotation sets the [`proxy_http_version`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_http_version) that the Nginx reverse proxy will use to communicate with the backend. +By default this is set to "1.1". + +```yaml +nginx.ingress.kubernetes.io/proxy-http-version: "1.0" +``` + ### SSL ciphers Specifies the [enabled ciphers](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers). diff --git a/internal/ingress/annotations/proxy/main.go b/internal/ingress/annotations/proxy/main.go index aafc9d5d85..478aa41b2d 100644 --- a/internal/ingress/annotations/proxy/main.go +++ b/internal/ingress/annotations/proxy/main.go @@ -40,6 +40,7 @@ type Config struct { ProxyRedirectTo string `json:"proxyRedirectTo"` RequestBuffering string `json:"requestBuffering"` ProxyBuffering string `json:"proxyBuffering"` + ProxyHTTPVersion string `json:"proxyHTTPVersion"` } // Equal tests for equality between two Configuration types @@ -95,6 +96,9 @@ func (l1 *Config) Equal(l2 *Config) bool { if l1.ProxyBuffering != l2.ProxyBuffering { return false } + if l1.ProxyHTTPVersion != l2.ProxyHTTPVersion { + return false + } return true } @@ -191,5 +195,10 @@ func (a proxy) Parse(ing *networking.Ingress) (interface{}, error) { config.ProxyBuffering = defBackend.ProxyBuffering } + config.ProxyHTTPVersion, err = parser.GetStringAnnotation("proxy-http-version", ing) + if err != nil { + config.ProxyHTTPVersion = defBackend.ProxyHTTPVersion + } + return config, nil } diff --git a/internal/ingress/annotations/proxy/main_test.go b/internal/ingress/annotations/proxy/main_test.go index 8520312e70..a6fe919cf7 100644 --- a/internal/ingress/annotations/proxy/main_test.go +++ b/internal/ingress/annotations/proxy/main_test.go @@ -81,6 +81,7 @@ func (m mockBackend) GetDefaultBackend() defaults.Backend { ProxyNextUpstreamTries: 3, ProxyRequestBuffering: "on", ProxyBuffering: "off", + ProxyHTTPVersion: "1.1", } } @@ -99,6 +100,7 @@ func TestProxy(t *testing.T) { data[parser.GetAnnotationWithPrefix("proxy-next-upstream-tries")] = "3" data[parser.GetAnnotationWithPrefix("proxy-request-buffering")] = "off" data[parser.GetAnnotationWithPrefix("proxy-buffering")] = "on" + data[parser.GetAnnotationWithPrefix("proxy-http-version")] = "1.0" ing.SetAnnotations(data) i, err := NewParser(mockBackend{}).Parse(ing) @@ -142,6 +144,9 @@ func TestProxy(t *testing.T) { if p.ProxyBuffering != "on" { t.Errorf("expected on as proxy-buffering but returned %v", p.ProxyBuffering) } + if p.ProxyHTTPVersion != "1.0" { + t.Errorf("expected 1.0 as proxy-http-version but returned %v", p.ProxyHTTPVersion) + } } func TestProxyWithNoAnnotation(t *testing.T) { @@ -188,4 +193,7 @@ func TestProxyWithNoAnnotation(t *testing.T) { if p.RequestBuffering != "on" { t.Errorf("expected on as request-buffering but returned %v", p.RequestBuffering) } + if p.ProxyHTTPVersion != "1.1" { + t.Errorf("expected 1.1 as proxy-http-version but returned %v", p.ProxyHTTPVersion) + } } diff --git a/internal/ingress/controller/config/config.go b/internal/ingress/controller/config/config.go index ac41ebb272..afd6ce0a02 100644 --- a/internal/ingress/controller/config/config.go +++ b/internal/ingress/controller/config/config.go @@ -437,6 +437,10 @@ type Configuration struct { // Default: 1 ProxyStreamResponses int `json:"proxy-stream-responses,omitempty"` + // Modifies the HTTP version the proxy uses to interact with the backend. + // http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_http_version + ProxyHTTPVersion string `json:"proxy-http-version"` + // Sets the ipv4 addresses on which the server will accept requests. BindAddressIpv4 []string `json:"bind-address-ipv4,omitempty"` @@ -715,6 +719,7 @@ func NewDefault() Configuration { LimitRate: 0, LimitRateAfter: 0, ProxyBuffering: "off", + ProxyHTTPVersion: "1.1", }, UpstreamKeepaliveConnections: 32, UpstreamKeepaliveTimeout: 60, diff --git a/internal/ingress/controller/controller.go b/internal/ingress/controller/controller.go index d9f4b7d6aa..e37e085532 100644 --- a/internal/ingress/controller/controller.go +++ b/internal/ingress/controller/controller.go @@ -927,6 +927,7 @@ func (n *NGINXController) createServers(data []*ingress.Ingress, RequestBuffering: bdef.ProxyRequestBuffering, ProxyRedirectFrom: bdef.ProxyRedirectFrom, ProxyBuffering: bdef.ProxyBuffering, + ProxyHTTPVersion: bdef.ProxyHTTPVersion, } defaultCertificate := n.cfg.FakeCertificate diff --git a/internal/ingress/defaults/main.go b/internal/ingress/defaults/main.go index b492f6ba31..a2260dce88 100644 --- a/internal/ingress/defaults/main.go +++ b/internal/ingress/defaults/main.go @@ -150,4 +150,8 @@ type Backend struct { // Enables or disables buffering of responses from the proxied server. // http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering ProxyBuffering string `json:"proxy-buffering"` + + // Modifies the HTTP version the proxy uses to interact with the backend. + // http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_http_version + ProxyHTTPVersion string `json:"proxy-http-version"` } diff --git a/rootfs/etc/nginx/template/nginx.tmpl b/rootfs/etc/nginx/template/nginx.tmpl index 14478afd36..12cdf95e91 100755 --- a/rootfs/etc/nginx/template/nginx.tmpl +++ b/rootfs/etc/nginx/template/nginx.tmpl @@ -930,8 +930,8 @@ stream { proxy_buffer_size {{ $location.Proxy.BufferSize }}; proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; + proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; - proxy_http_version 1.1; proxy_ssl_server_name on; proxy_pass_request_headers on; {{ if isValidByteSize $location.Proxy.BodySize true }} @@ -1227,8 +1227,7 @@ stream { proxy_buffer_size {{ $location.Proxy.BufferSize }}; proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; - - proxy_http_version 1.1; + proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; proxy_cookie_domain {{ $location.Proxy.CookieDomain }}; proxy_cookie_path {{ $location.Proxy.CookiePath }}; diff --git a/test/e2e/annotations/proxy.go b/test/e2e/annotations/proxy.go index 8a12d63380..f76cd1d2ec 100644 --- a/test/e2e/annotations/proxy.go +++ b/test/e2e/annotations/proxy.go @@ -230,4 +230,19 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() { strings.Contains(server, "proxy_cookie_path /one/ /;") }) }) + + It("should change the default proxy HTTP version", func() { + annotations := map[string]string{ + "nginx.ingress.kubernetes.io/proxy-http-version": "1.0", + } + + ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, &annotations) + f.EnsureIngress(ing) + + f.WaitForNginxServer(host, + func(server string) bool { + return strings.Contains(server, "proxy_http_version 1.0;") + }) + }) + })