You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by zh...@apache.org on 2022/05/11 03:25:54 UTC
[apisix-ingress-controller] branch master updated: feat: update an redirect annotation for ingress resource (#975)
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 <79...@users.noreply.github.com>
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")
+ })
})