This is an automated email from the ASF dual-hosted git repository.

zhangjintao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git


The following commit(s) were added to refs/heads/master by this push:
     new 78efb006 feat: update an redirect annotation for  ingress resource 
(#975)
78efb006 is described below

commit 78efb006a4285a9c558cb50524478f944f849906
Author: Xin Rong <[email protected]>
AuthorDate: Wed May 11 11:25:49 2022 +0800

    feat: update an redirect annotation for  ingress resource (#975)
---
 pkg/kube/translation/annotations/redirect.go |  17 ++-
 pkg/types/apisix/v1/plugin_types.go          |   4 +-
 test/e2e/suite-annotations/redirect.go       | 200 +++++++++++++++++++++++++++
 3 files changed, 219 insertions(+), 2 deletions(-)

diff --git a/pkg/kube/translation/annotations/redirect.go 
b/pkg/kube/translation/annotations/redirect.go
index c162d84a..6f2ca9af 100644
--- a/pkg/kube/translation/annotations/redirect.go
+++ b/pkg/kube/translation/annotations/redirect.go
@@ -15,11 +15,16 @@
 package annotations
 
 import (
+       "net/http"
+       "strconv"
+
        apisixv1 
"github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
 )
 
 const (
-       _httpToHttps = AnnotationsPrefix + "http-to-https"
+       _httpToHttps      = AnnotationsPrefix + "http-to-https"
+       _httpRedirect     = AnnotationsPrefix + "http-redirect"
+       _httpRedirectCode = AnnotationsPrefix + "http-redirect-code"
 )
 
 type redirect struct{}
@@ -37,9 +42,19 @@ func (r *redirect) PluginName() string {
 func (r *redirect) Handle(e Extractor) (interface{}, error) {
        var plugin apisixv1.RedirectConfig
        plugin.HttpToHttps = e.GetBoolAnnotation(_httpToHttps)
+       plugin.URI = e.GetStringAnnotation(_httpRedirect)
+       // Transformation fail defaults to 0.
+       plugin.RetCode, _ = 
strconv.Atoi(e.GetStringAnnotation(_httpRedirectCode))
        // To avoid empty redirect plugin config, adding the check about the 
redirect.
        if plugin.HttpToHttps {
                return &plugin, nil
        }
+       if plugin.URI != "" {
+               // Default is http.StatusMovedPermanently, the allowed value is 
between http.StatusMultipleChoices and http.StatusPermanentRedirect.
+               if plugin.RetCode < http.StatusMovedPermanently || 
plugin.RetCode > http.StatusPermanentRedirect {
+                       plugin.RetCode = http.StatusMovedPermanently
+               }
+               return &plugin, nil
+       }
        return nil, nil
 }
diff --git a/pkg/types/apisix/v1/plugin_types.go 
b/pkg/types/apisix/v1/plugin_types.go
index daf0c432..51346b78 100644
--- a/pkg/types/apisix/v1/plugin_types.go
+++ b/pkg/types/apisix/v1/plugin_types.go
@@ -85,7 +85,9 @@ type RewriteConfig struct {
 // RedirectConfig is the rule config for redirect plugin.
 // +k8s:deepcopy-gen=true
 type RedirectConfig struct {
-       HttpToHttps bool `json:"http_to_https,omitempty"`
+       HttpToHttps bool   `json:"http_to_https,omitempty"`
+       URI         string `json:"uri,omitempty"`
+       RetCode     int    `json:"ret_code,omitempty"`
 }
 
 // ForwardAuthConfig is the rule config for forward-auth plugin.
diff --git a/test/e2e/suite-annotations/redirect.go 
b/test/e2e/suite-annotations/redirect.go
index 02275117..6fade7d2 100644
--- a/test/e2e/suite-annotations/redirect.go
+++ b/test/e2e/suite-annotations/redirect.go
@@ -19,6 +19,7 @@ import (
        "net/http"
        "time"
 
+       "github.com/gavv/httpexpect/v2"
        "github.com/onsi/ginkgo"
        "github.com/stretchr/testify/assert"
 
@@ -119,4 +120,203 @@ spec:
                resp.Status(http.StatusMovedPermanently)
                resp.Header("Location").Equal("https://httpbin.org/sample";)
        })
+
+       ginkgo.It("redirect http-redirect in ingress networking/v1", func() {
+               backendSvc, backendPort := s.DefaultHTTPBackend()
+               ing := fmt.Sprintf(`
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  annotations:
+    kubernetes.io/ingress.class: apisix
+    k8s.apisix.apache.org/http-redirect: "/anything$uri"
+    k8s.apisix.apache.org/http-redirect-code: "308"
+  name: ingress-v1
+spec:
+  rules:
+  - host: httpbin.org
+    http:
+      paths:
+      - path: /*
+        pathType: Exact
+        backend:
+          service:
+            name: %s
+            port:
+              number: %d
+`, backendSvc, backendPort[0])
+               err := s.CreateResourceFromString(ing)
+               assert.Nil(ginkgo.GinkgoT(), err, "creating ingress")
+               time.Sleep(5 * time.Second)
+
+               resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", 
"httpbin.org").Expect()
+               resp.Status(http.StatusPermanentRedirect)
+               resp.Header("Location").Equal("/anything/ip")
+       })
+
+       ginkgo.It("redirect http-redirect in ingress networking/v1beta1", 
func() {
+               backendSvc, backendPort := s.DefaultHTTPBackend()
+               ing := fmt.Sprintf(`
+apiVersion: networking.k8s.io/v1beta1
+kind: Ingress
+metadata:
+  annotations:
+    kubernetes.io/ingress.class: apisix
+    k8s.apisix.apache.org/http-redirect: "/anything$uri"
+    k8s.apisix.apache.org/http-redirect-code: "308"
+  name: ingress-v1beta1
+spec:
+  rules:
+  - host: httpbin.org
+    http:
+      paths:
+      - path: /*
+        pathType: Exact
+        backend:
+          serviceName: %s
+          servicePort: %d
+`, backendSvc, backendPort[0])
+               err := s.CreateResourceFromString(ing)
+               assert.Nil(ginkgo.GinkgoT(), err, "creating ingress")
+               time.Sleep(5 * time.Second)
+
+               resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", 
"httpbin.org").Expect()
+               resp.Status(http.StatusPermanentRedirect)
+               resp.Header("Location").Equal("/anything/ip")
+       })
+
+       ginkgo.It("redirect http-redirect in ingress extensions/v1beta1", 
func() {
+               backendSvc, backendPort := s.DefaultHTTPBackend()
+               ing := fmt.Sprintf(`
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+  annotations:
+    kubernetes.io/ingress.class: apisix
+    k8s.apisix.apache.org/http-redirect: "/anything$uri"
+    k8s.apisix.apache.org/http-redirect-code: "308"
+  name: ingress-extensions-v1beta1
+spec:
+  rules:
+  - host: httpbin.org
+    http:
+      paths:
+      - path: /*
+        pathType: Exact
+        backend:
+          serviceName: %s
+          servicePort: %d
+`, backendSvc, backendPort[0])
+               err := s.CreateResourceFromString(ing)
+               assert.Nil(ginkgo.GinkgoT(), err, "creating ingress")
+               time.Sleep(5 * time.Second)
+
+               resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", 
"httpbin.org").Expect()
+               resp.Status(http.StatusPermanentRedirect)
+               resp.Header("Location").Equal("/anything/ip")
+       })
+
+       ginkgo.It("redirect http-redirect external link in ingress 
networking/v1", func() {
+               backendSvc, backendPort := s.DefaultHTTPBackend()
+               ing := fmt.Sprintf(`
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  annotations:
+    kubernetes.io/ingress.class: apisix
+    k8s.apisix.apache.org/http-redirect: "https://httpbin.org/get";
+    k8s.apisix.apache.org/http-redirect-code: "308"
+  name: ingress-v1
+spec:
+  rules:
+  - host: httpbin.org
+    http:
+      paths:
+      - path: /*
+        pathType: Exact
+        backend:
+          service:
+            name: %s
+            port:
+              number: %d
+`, backendSvc, backendPort[0])
+               err := s.CreateResourceFromString(ing)
+               assert.Nil(ginkgo.GinkgoT(), err, "creating ingress")
+               time.Sleep(5 * time.Second)
+
+               resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", 
"httpbin.org").Expect()
+               resp.Status(http.StatusPermanentRedirect)
+               url := 
resp.Header("Location").Equal("https://httpbin.org/get";).Raw()
+
+               body := httpexpect.New(ginkgo.GinkgoT(), 
url).GET("").Expect().Status(http.StatusOK).Body().Raw()
+               assert.Contains(ginkgo.GinkgoT(), body, 
"https://httpbin.org/get";)
+       })
+
+       ginkgo.It("redirect http-redirect external link in ingress 
networking/v1beta1", func() {
+               backendSvc, backendPort := s.DefaultHTTPBackend()
+               ing := fmt.Sprintf(`
+apiVersion: networking.k8s.io/v1beta1
+kind: Ingress
+metadata:
+  annotations:
+    kubernetes.io/ingress.class: apisix
+    k8s.apisix.apache.org/http-redirect: "https://httpbin.org/get";
+    k8s.apisix.apache.org/http-redirect-code: "308"
+  name: ingress-v1beta1
+spec:
+  rules:
+  - host: httpbin.org
+    http:
+      paths:
+      - path: /*
+        pathType: Exact
+        backend:
+          serviceName: %s
+          servicePort: %d
+`, backendSvc, backendPort[0])
+               err := s.CreateResourceFromString(ing)
+               assert.Nil(ginkgo.GinkgoT(), err, "creating ingress")
+               time.Sleep(5 * time.Second)
+
+               resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", 
"httpbin.org").Expect()
+               resp.Status(http.StatusPermanentRedirect)
+               url := 
resp.Header("Location").Equal("https://httpbin.org/get";).Raw()
+
+               body := httpexpect.New(ginkgo.GinkgoT(), 
url).GET("").Expect().Status(http.StatusOK).Body().Raw()
+               assert.Contains(ginkgo.GinkgoT(), body, 
"https://httpbin.org/get";)
+       })
+
+       ginkgo.It("redirect http-redirect external link in ingress 
extensions/v1beta1", func() {
+               backendSvc, backendPort := s.DefaultHTTPBackend()
+               ing := fmt.Sprintf(`
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+  annotations:
+    kubernetes.io/ingress.class: apisix
+    k8s.apisix.apache.org/http-redirect: "https://httpbin.org/get";
+    k8s.apisix.apache.org/http-redirect-code: "308"
+  name: ingress-extensions-v1beta1
+spec:
+  rules:
+  - host: httpbin.org
+    http:
+      paths:
+      - path: /*
+        pathType: Exact
+        backend:
+          serviceName: %s
+          servicePort: %d
+`, backendSvc, backendPort[0])
+               err := s.CreateResourceFromString(ing)
+               assert.Nil(ginkgo.GinkgoT(), err, "creating ingress")
+               time.Sleep(5 * time.Second)
+
+               resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", 
"httpbin.org").Expect()
+               resp.Status(http.StatusPermanentRedirect)
+               url := 
resp.Header("Location").Equal("https://httpbin.org/get";).Raw()
+
+               body := httpexpect.New(ginkgo.GinkgoT(), 
url).GET("").Expect().Status(http.StatusOK).Body().Raw()
+               assert.Contains(ginkgo.GinkgoT(), body, 
"https://httpbin.org/get";)
+       })
 })

Reply via email to