Skip to content

Commit

Permalink
feat: update an redirect annotation for ingress resource (#975)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlinsRan committed May 11, 2022
1 parent 3a175e5 commit 78efb00
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 2 deletions.
17 changes: 16 additions & 1 deletion pkg/kube/translation/annotations/redirect.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
Expand All @@ -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
}
4 changes: 3 additions & 1 deletion pkg/types/apisix/v1/plugin_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
200 changes: 200 additions & 0 deletions test/e2e/suite-annotations/redirect.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"net/http"
"time"

"github.com/gavv/httpexpect/v2"
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"

Expand Down Expand Up @@ -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")
})
})

0 comments on commit 78efb00

Please sign in to comment.