From 859b298d42b6e3a5d02535ddca0ac91e799b2e8b Mon Sep 17 00:00:00 2001 From: Manuel Alejandro de Brito Fontes Date: Mon, 8 Oct 2018 12:26:06 -0300 Subject: [PATCH] Remove annotations grpc-backend and secure-backend already deprecated --- docs/examples/grpc/README.md | 5 +- .../nginx-configuration/annotations.md | 28 ------- internal/ingress/annotations/annotations.go | 3 - .../ingress/annotations/annotations_test.go | 36 ++------- internal/ingress/annotations/grpc/main.go | 44 ---------- .../ingress/annotations/grpc/main_test.go | 80 ------------------- .../annotations/secureupstream/main.go | 8 +- .../annotations/secureupstream/main_test.go | 6 +- internal/ingress/controller/controller.go | 10 --- internal/ingress/controller/nginx.go | 1 - .../ingress/controller/template/template.go | 15 +--- .../controller/template/template_test.go | 68 +++++++++++----- internal/ingress/types.go | 8 -- internal/ingress/types_equals.go | 6 -- 14 files changed, 64 insertions(+), 254 deletions(-) delete mode 100644 internal/ingress/annotations/grpc/main.go delete mode 100644 internal/ingress/annotations/grpc/main_test.go diff --git a/docs/examples/grpc/README.md b/docs/examples/grpc/README.md index f2a6144bbb..0416f5e07f 100644 --- a/docs/examples/grpc/README.md +++ b/docs/examples/grpc/README.md @@ -48,8 +48,7 @@ inside the cluster and arrive "insecure"). For your own application you may or may not want to do this. If you prefer to forward encrypted traffic to your POD and terminate TLS at the gRPC server -itself, add the ingress annotation `nginx.ingress.kubernetes.io/secure-backends: -"true"`. +itself, add the ingress annotation `nginx.ingress.kubernetes.io/backend-protocol: "GRPCS"`. ### Step 2: the kubernetes `Service` @@ -69,7 +68,7 @@ $ kubectl create -f ingress.yaml A few things to note: 1. We've tagged the ingress with the annotation - `nginx.ingress.kubernetes.io/grpc-backend: "true"`. This is the magic + `nginx.ingress.kubernetes.io/backend-protocol: "GRPC"`. This is the magic ingredient that sets up the appropriate nginx configuration to route http/2 traffic to our service. 1. We're terminating TLS at the ingress and have configured an SSL certificate diff --git a/docs/user-guide/nginx-configuration/annotations.md b/docs/user-guide/nginx-configuration/annotations.md index b8f1c4a103..b1a771643f 100644 --- a/docs/user-guide/nginx-configuration/annotations.md +++ b/docs/user-guide/nginx-configuration/annotations.md @@ -40,7 +40,6 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz |[nginx.ingress.kubernetes.io/cors-max-age](#enable-cors)|number| |[nginx.ingress.kubernetes.io/force-ssl-redirect](#server-side-https-enforcement-through-redirect)|"true" or "false"| |[nginx.ingress.kubernetes.io/from-to-www-redirect](#redirect-from-to-www)|"true" or "false"| -|[nginx.ingress.kubernetes.io/grpc-backend](#grpc-backend)|"true" or "false"| |[nginx.ingress.kubernetes.io/limit-connections](#rate-limiting)|number| |[nginx.ingress.kubernetes.io/limit-rps](#rate-limiting)|number| |[nginx.ingress.kubernetes.io/permanent-redirect](#permanent-redirect)|string| @@ -58,7 +57,6 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz |[nginx.ingress.kubernetes.io/proxy-redirect-to](#proxy-redirect)|string| |[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/secure-backends](#secure-backends)|"true" or "false"| |[nginx.ingress.kubernetes.io/secure-verify-ca-secret](#secure-backends)|string| |[nginx.ingress.kubernetes.io/server-alias](#server-alias)|string| |[nginx.ingress.kubernetes.io/server-snippet](#server-snippet)|string| @@ -393,19 +391,6 @@ the User guide. Because SSL Passthrough works on layer 4 of the OSI model (TCP) and not on the layer 7 (HTTP), using SSL Passthrough invalidates all the other annotations set on an Ingress object. -### Secure backends DEPRECATED (since 0.18.0) - -Please use `nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"` - -By default NGINX uses plain HTTP to reach the services. -Adding the annotation `nginx.ingress.kubernetes.io/secure-backends: "true"` in the Ingress rule changes the protocol to HTTPS. -If you want to validate the upstream against a specific certificate, you can create a secret with it and reference the secret with the annotation `nginx.ingress.kubernetes.io/secure-verify-ca-secret`. - -!!! attention - - Note that if an invalid or non-existent secret is given, - the ingress controller will ignore the `secure-backends` annotation. - ### Service Upstream By default the NGINX ingress controller uses a list of all endpoints (Pod IP/port) in the NGINX upstream configuration. @@ -588,19 +573,6 @@ nginx.ingress.kubernetes.io/lua-resty-waf-extra-rules: '[=[ { "access": [ { "act For details on how to write WAF rules, please refer to [https://github.com/p0pr0ck5/lua-resty-waf](https://github.com/p0pr0ck5/lua-resty-waf). -### gRPC backend DEPRECATED (since 0.18.0) - -Please use `nginx.ingress.kubernetes.io/backend-protocol: "GRPC"` or `nginx.ingress.kubernetes.io/backend-protocol: "GRPCS"` - -Since NGINX 1.13.10 it is possible to expose [gRPC services natively](http://nginx.org/en/docs/http/ngx_http_grpc_module.html) - -You only need to add the annotation `nginx.ingress.kubernetes.io/grpc-backend: "true"` to enable this feature. -Additionally, if the gRPC service requires TLS, add `nginx.ingress.kubernetes.io/secure-backends: "true"`. - -!!! attention - This feature requires HTTP2 to work which means we need to expose this service using HTTPS. - Exposing a gRPC service using HTTP is not supported. - [configmap]: ./configmap.md ### InfluxDB diff --git a/internal/ingress/annotations/annotations.go b/internal/ingress/annotations/annotations.go index 34c8a91b84..d137c52c3b 100644 --- a/internal/ingress/annotations/annotations.go +++ b/internal/ingress/annotations/annotations.go @@ -34,7 +34,6 @@ import ( "k8s.io/ingress-nginx/internal/ingress/annotations/connection" "k8s.io/ingress-nginx/internal/ingress/annotations/cors" "k8s.io/ingress-nginx/internal/ingress/annotations/defaultbackend" - "k8s.io/ingress-nginx/internal/ingress/annotations/grpc" "k8s.io/ingress-nginx/internal/ingress/annotations/healthcheck" "k8s.io/ingress-nginx/internal/ingress/annotations/influxdb" "k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist" @@ -95,7 +94,6 @@ type Ingress struct { XForwardedPrefix bool SSLCiphers string Logs log.Config - GRPC bool LuaRestyWAF luarestywaf.Config InfluxDB influxdb.Config } @@ -136,7 +134,6 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor { "XForwardedPrefix": xforwardedprefix.NewParser(cfg), "SSLCiphers": sslcipher.NewParser(cfg), "Logs": log.NewParser(cfg), - "GRPC": grpc.NewParser(cfg), "LuaRestyWAF": luarestywaf.NewParser(cfg), "InfluxDB": influxdb.NewParser(cfg), "BackendProtocol": backendprotocol.NewParser(cfg), diff --git a/internal/ingress/annotations/annotations_test.go b/internal/ingress/annotations/annotations_test.go index 7294998368..6d7947c990 100644 --- a/internal/ingress/annotations/annotations_test.go +++ b/internal/ingress/annotations/annotations_test.go @@ -30,7 +30,6 @@ import ( ) var ( - annotationSecureUpstream = parser.GetAnnotationWithPrefix("secure-backends") annotationSecureVerifyCACert = parser.GetAnnotationWithPrefix("secure-verify-ca-secret") annotationUpsMaxFails = parser.GetAnnotationWithPrefix("upstream-max-fails") annotationUpsFailTimeout = parser.GetAnnotationWithPrefix("upstream-fail-timeout") @@ -40,6 +39,7 @@ var ( annotationCorsAllowMethods = parser.GetAnnotationWithPrefix("cors-allow-methods") annotationCorsAllowHeaders = parser.GetAnnotationWithPrefix("cors-allow-headers") annotationCorsAllowCredentials = parser.GetAnnotationWithPrefix("cors-allow-credentials") + backendProtocol = parser.GetAnnotationWithPrefix("backend-protocol") defaultCorsMethods = "GET, PUT, POST, DELETE, PATCH, OPTIONS" defaultCorsHeaders = "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization" annotationAffinityCookieName = parser.GetAnnotationWithPrefix("session-cookie-name") @@ -111,30 +111,6 @@ func buildIngress() *extensions.Ingress { } } -func TestSecureUpstream(t *testing.T) { - ec := NewAnnotationExtractor(mockCfg{}) - ing := buildIngress() - - fooAnns := []struct { - annotations map[string]string - er bool - }{ - {map[string]string{annotationSecureUpstream: "true"}, true}, - {map[string]string{annotationSecureUpstream: "false"}, false}, - {map[string]string{annotationSecureUpstream + "_no": "true"}, false}, - {map[string]string{}, false}, - {nil, false}, - } - - for _, foo := range fooAnns { - ing.SetAnnotations(foo.annotations) - r := ec.Extract(ing).SecureUpstream - if r.Secure != foo.er { - t.Errorf("Returned %v but expected %v", r, foo.er) - } - } -} - func TestSecureVerifyCACert(t *testing.T) { ec := NewAnnotationExtractor(mockCfg{ MockSecrets: map[string]*apiv1.Secret{ @@ -151,11 +127,11 @@ func TestSecureVerifyCACert(t *testing.T) { annotations map[string]string exists bool }{ - {1, map[string]string{annotationSecureUpstream: "true", annotationSecureVerifyCACert: "not"}, false}, - {2, map[string]string{annotationSecureUpstream: "false", annotationSecureVerifyCACert: "secure-verify-ca"}, false}, - {3, map[string]string{annotationSecureUpstream: "true", annotationSecureVerifyCACert: "secure-verify-ca"}, true}, - {4, map[string]string{annotationSecureUpstream: "true", annotationSecureVerifyCACert + "_not": "secure-verify-ca"}, false}, - {5, map[string]string{annotationSecureUpstream: "true"}, false}, + {1, map[string]string{backendProtocol: "HTTPS", annotationSecureVerifyCACert: "not"}, false}, + {2, map[string]string{backendProtocol: "HTTP", annotationSecureVerifyCACert: "secure-verify-ca"}, false}, + {3, map[string]string{backendProtocol: "HTTPS", annotationSecureVerifyCACert: "secure-verify-ca"}, true}, + {4, map[string]string{backendProtocol: "HTTPS", annotationSecureVerifyCACert + "_not": "secure-verify-ca"}, false}, + {5, map[string]string{backendProtocol: "HTTPS"}, false}, {6, map[string]string{}, false}, {7, nil, false}, } diff --git a/internal/ingress/annotations/grpc/main.go b/internal/ingress/annotations/grpc/main.go deleted file mode 100644 index 98036ee6a9..0000000000 --- a/internal/ingress/annotations/grpc/main.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package grpc - -import ( - extensions "k8s.io/api/extensions/v1beta1" - - "k8s.io/ingress-nginx/internal/ingress/annotations/parser" - ing_errors "k8s.io/ingress-nginx/internal/ingress/errors" - "k8s.io/ingress-nginx/internal/ingress/resolver" -) - -type grpc struct { - r resolver.Resolver -} - -// NewParser creates a new gRPC annotation parser -func NewParser(r resolver.Resolver) parser.IngressAnnotation { - return grpc{r} -} - -// ParseAnnotations parses the annotations contained in the ingress -// rule used to indicate if the Kubernetes service exposes gRPC -func (a grpc) Parse(ing *extensions.Ingress) (interface{}, error) { - if ing.GetAnnotations() == nil { - return false, ing_errors.ErrMissingAnnotations - } - - return parser.GetBoolAnnotation("grpc-backend", ing) -} diff --git a/internal/ingress/annotations/grpc/main_test.go b/internal/ingress/annotations/grpc/main_test.go deleted file mode 100644 index fccc1138ca..0000000000 --- a/internal/ingress/annotations/grpc/main_test.go +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package grpc - -import ( - "testing" - - api "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/ingress-nginx/internal/ingress/annotations/parser" - "k8s.io/ingress-nginx/internal/ingress/resolver" - - "k8s.io/apimachinery/pkg/util/intstr" -) - -func buildIngress() *extensions.Ingress { - return &extensions.Ingress{ - ObjectMeta: meta_v1.ObjectMeta{ - Name: "foo", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.IngressSpec{ - Backend: &extensions.IngressBackend{ - ServiceName: "default-backend", - ServicePort: intstr.FromInt(80), - }, - }, - } -} - -func TestParseAnnotations(t *testing.T) { - ing := buildIngress() - - _, err := NewParser(&resolver.Mock{}).Parse(ing) - if err == nil { - t.Errorf("unexpected error: %v", err) - } - - data := map[string]string{} - data[parser.GetAnnotationWithPrefix("grpc-backend")] = "true" - ing.SetAnnotations(data) - // test ingress using the annotation without a TLS section - _, err = NewParser(&resolver.Mock{}).Parse(ing) - if err != nil { - t.Errorf("unexpected error parsing ingress with sslpassthrough") - } - - // test with a valid host - ing.Spec.TLS = []extensions.IngressTLS{ - { - Hosts: []string{"foo.bar.com"}, - }, - } - i, err := NewParser(&resolver.Mock{}).Parse(ing) - if err != nil { - t.Errorf("expected error parsing ingress with sslpassthrough") - } - val, ok := i.(bool) - if !ok { - t.Errorf("expected a bool type") - } - if !val { - t.Errorf("expected true but false returned") - } -} diff --git a/internal/ingress/annotations/secureupstream/main.go b/internal/ingress/annotations/secureupstream/main.go index e973dacbc0..f1f97a9539 100644 --- a/internal/ingress/annotations/secureupstream/main.go +++ b/internal/ingress/annotations/secureupstream/main.go @@ -28,7 +28,6 @@ import ( // Config describes SSL backend configuration type Config struct { - Secure bool `json:"secure"` CACert resolver.AuthSSLCert `json:"caCert"` } @@ -44,13 +43,13 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation { // Parse parses the annotations contained in the ingress // rule used to indicate if the upstream servers should use SSL func (a su) Parse(ing *extensions.Ingress) (interface{}, error) { - s, _ := parser.GetBoolAnnotation("secure-backends", ing) + bp, _ := parser.GetStringAnnotation("backend-protocol", ing) ca, _ := parser.GetStringAnnotation("secure-verify-ca-secret", ing) secure := &Config{ - Secure: s, CACert: resolver.AuthSSLCert{}, } - if !s && ca != "" { + + if (bp != "HTTPS" && bp != "GRPCS") && ca != "" { return secure, errors.Errorf("trying to use CA from secret %v/%v on a non secure backend", ing.Namespace, ca) } @@ -65,7 +64,6 @@ func (a su) Parse(ing *extensions.Ingress) (interface{}, error) { return secure, nil } return &Config{ - Secure: s, CACert: *caCert, }, nil } diff --git a/internal/ingress/annotations/secureupstream/main_test.go b/internal/ingress/annotations/secureupstream/main_test.go index 13a7c4e2c1..adee3c63ae 100644 --- a/internal/ingress/annotations/secureupstream/main_test.go +++ b/internal/ingress/annotations/secureupstream/main_test.go @@ -79,7 +79,7 @@ func (cfg mockCfg) GetAuthCertificate(secret string) (*resolver.AuthSSLCert, err func TestAnnotations(t *testing.T) { ing := buildIngress() data := map[string]string{} - data[parser.GetAnnotationWithPrefix("secure-backends")] = "true" + data[parser.GetAnnotationWithPrefix("backend-protocol")] = "HTTPS" data[parser.GetAnnotationWithPrefix("secure-verify-ca-secret")] = "secure-verify-ca" ing.SetAnnotations(data) @@ -96,7 +96,7 @@ func TestAnnotations(t *testing.T) { func TestSecretNotFound(t *testing.T) { ing := buildIngress() data := map[string]string{} - data[parser.GetAnnotationWithPrefix("secure-backends")] = "true" + data[parser.GetAnnotationWithPrefix("backend-protocol")] = "HTTPS" data[parser.GetAnnotationWithPrefix("secure-verify-ca-secret")] = "secure-verify-ca" ing.SetAnnotations(data) _, err := NewParser(mockCfg{}).Parse(ing) @@ -108,7 +108,7 @@ func TestSecretNotFound(t *testing.T) { func TestSecretOnNonSecure(t *testing.T) { ing := buildIngress() data := map[string]string{} - data[parser.GetAnnotationWithPrefix("secure-backends")] = "false" + data[parser.GetAnnotationWithPrefix("backend-protocol")] = "HTTP" data[parser.GetAnnotationWithPrefix("secure-verify-ca-secret")] = "secure-verify-ca" ing.SetAnnotations(data) _, err := NewParser(mockCfg{ diff --git a/internal/ingress/controller/controller.go b/internal/ingress/controller/controller.go index d9afb87b95..88d32b6119 100644 --- a/internal/ingress/controller/controller.go +++ b/internal/ingress/controller/controller.go @@ -348,7 +348,6 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([] loc.UsePortInRedirects = anns.UsePortInRedirects loc.Connection = anns.Connection loc.Logs = anns.Logs - loc.GRPC = anns.GRPC loc.LuaRestyWAF = anns.LuaRestyWAF loc.InfluxDB = anns.InfluxDB loc.DefaultBackend = anns.DefaultBackend @@ -389,7 +388,6 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([] UsePortInRedirects: anns.UsePortInRedirects, Connection: anns.Connection, Logs: anns.Logs, - GRPC: anns.GRPC, LuaRestyWAF: anns.LuaRestyWAF, InfluxDB: anns.InfluxDB, DefaultBackend: anns.DefaultBackend, @@ -523,9 +521,6 @@ func (n *NGINXController) createUpstreams(data []*extensions.Ingress, du *ingres glog.V(3).Infof("Creating upstream %q", defBackend) upstreams[defBackend] = newUpstream(defBackend) - if !upstreams[defBackend].Secure { - upstreams[defBackend].Secure = anns.SecureUpstream.Secure - } if upstreams[defBackend].SecureCACert.Secret == "" { upstreams[defBackend].SecureCACert = anns.SecureUpstream.CACert } @@ -577,10 +572,6 @@ func (n *NGINXController) createUpstreams(data []*extensions.Ingress, du *ingres upstreams[name] = newUpstream(name) upstreams[name].Port = path.Backend.ServicePort - if !upstreams[name].Secure { - upstreams[name].Secure = anns.SecureUpstream.Secure - } - if upstreams[name].SecureCACert.Secret == "" { upstreams[name].SecureCACert = anns.SecureUpstream.CACert } @@ -835,7 +826,6 @@ func (n *NGINXController) createServers(data []*extensions.Ingress, defLoc.UpstreamVhost = anns.UpstreamVhost defLoc.Whitelist = anns.Whitelist defLoc.Denied = anns.Denied - defLoc.GRPC = anns.GRPC defLoc.LuaRestyWAF = anns.LuaRestyWAF defLoc.InfluxDB = anns.InfluxDB } else { diff --git a/internal/ingress/controller/nginx.go b/internal/ingress/controller/nginx.go index aa4ccf86a4..4af6062143 100644 --- a/internal/ingress/controller/nginx.go +++ b/internal/ingress/controller/nginx.go @@ -763,7 +763,6 @@ func configureDynamically(pcfg *ingress.Configuration, port int, isDynamicCertif luaBackend := &ingress.Backend{ Name: backend.Name, Port: backend.Port, - Secure: backend.Secure, SSLPassthrough: backend.SSLPassthrough, SessionAffinity: backend.SessionAffinity, UpstreamHashBy: backend.UpstreamHashBy, diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index 2d5e5522c8..5013554923 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -456,12 +456,6 @@ func buildProxyPass(host string, b interface{}, loc interface{}, dynamicConfigur proxyPass = "ajp_pass" } - // TODO: Remove after the deprecation of grpc-backend annotation - if location.GRPC { - proxyPass = "grpc_pass" - proto = "grpc://" - } - upstreamName := "upstream_balancer" if !dynamicConfigurationEnabled { @@ -470,11 +464,10 @@ func buildProxyPass(host string, b interface{}, loc interface{}, dynamicConfigur for _, backend := range backends { if backend.Name == location.Backend { - if backend.Secure || backend.SSLPassthrough { - // TODO: Remove after the deprecation of secure-backend annotation + if backend.SSLPassthrough { proto = "https://" - // TODO: Remove after the deprecation of grpc-backend annotation - if location.GRPC { + + if location.BackendProtocol == "GRPCS" { proto = "grpcs://" } } @@ -974,7 +967,7 @@ func proxySetHeader(loc interface{}) string { return "proxy_set_header" } - if location.GRPC || location.BackendProtocol == "GRPC" || location.BackendProtocol == "GRPCS" { + if location.BackendProtocol == "GRPC" || location.BackendProtocol == "GRPCS" { return "grpc_set_header" } diff --git a/internal/ingress/controller/template/template_test.go b/internal/ingress/controller/template/template_test.go index d8622e2f66..5de8657d1c 100644 --- a/internal/ingress/controller/template/template_test.go +++ b/internal/ingress/controller/template/template_test.go @@ -63,7 +63,8 @@ var ( false, false, true, - false}, + false, + }, "when secure backend and stickeness enabled": { "/", "/", @@ -75,7 +76,8 @@ var ( false, false, true, - false}, + false, + }, "when secure backend and dynamic config enabled": { "/", "/", @@ -99,7 +101,8 @@ var ( false, true, true, - false}, + false, + }, "invalid redirect / to / with dynamic config enabled": { "/", "/", @@ -111,7 +114,8 @@ var ( false, true, false, - false}, + false, + }, "invalid redirect / to /": { "/", "/", @@ -123,7 +127,8 @@ var ( false, false, false, - false}, + false, + }, "redirect / to /jenkins": { "/", "/jenkins", @@ -139,7 +144,8 @@ proxy_pass http://upstream-name; false, false, false, - true}, + true, + }, "redirect /something to /": { "/something", "/", @@ -155,7 +161,8 @@ proxy_pass http://upstream-name; false, false, false, - true}, + true, + }, "redirect /end-with-slash/ to /not-root": { "/end-with-slash/", "/not-root", @@ -171,7 +178,8 @@ proxy_pass http://upstream-name; false, false, false, - true}, + true, + }, "redirect /something-complex to /not-root": { "/something-complex", "/not-root", @@ -187,7 +195,8 @@ proxy_pass http://upstream-name; false, false, false, - true}, + true, + }, "redirect / to /jenkins and rewrite": { "/", "/jenkins", @@ -206,7 +215,8 @@ subs_filter '(<(?:H|h)(?:E|e)(?:A|a)(?:D|d)(?:[^">]|"[^"]*")*>)' '$1]|"[^"]*")*>)' '$1]|"[^"]*")*>)' '$1]|"[^"]*")*>)' '$1]|"[^"]*")*>)' '$1