Add custom code handling for temporal redirect (#10651)
Co-authored-by: Ricardo Katz <rikatz@users.noreply.github.com>
This commit is contained in:
parent
ffee96c58c
commit
24450ea509
4 changed files with 70 additions and 6 deletions
|
|
@ -28,7 +28,10 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const defaultPermanentRedirectCode = http.StatusMovedPermanently
|
||||
const (
|
||||
defaultPermanentRedirectCode = http.StatusMovedPermanently
|
||||
defaultTemporalRedirectCode = http.StatusFound
|
||||
)
|
||||
|
||||
// Config returns the redirect configuration for an Ingress rule
|
||||
type Config struct {
|
||||
|
|
@ -40,6 +43,7 @@ type Config struct {
|
|||
const (
|
||||
fromToWWWRedirAnnotation = "from-to-www-redirect"
|
||||
temporalRedirectAnnotation = "temporal-redirect"
|
||||
temporalRedirectAnnotationCode = "temporal-redirect-code"
|
||||
permanentRedirectAnnotation = "permanent-redirect"
|
||||
permanentRedirectAnnotationCode = "permanent-redirect-code"
|
||||
)
|
||||
|
|
@ -60,6 +64,12 @@ var redirectAnnotations = parser.Annotation{
|
|||
Documentation: `This annotation allows you to return a temporal redirect (Return Code 302) instead of sending data to the upstream.
|
||||
For example setting this annotation to https://www.google.com would redirect everything to Google with a Return Code of 302 (Moved Temporarily).`,
|
||||
},
|
||||
temporalRedirectAnnotationCode: {
|
||||
Validator: parser.ValidateInt,
|
||||
Scope: parser.AnnotationScopeLocation,
|
||||
Risk: parser.AnnotationRiskLow, // Low, as it allows just a set of options
|
||||
Documentation: `This annotation allows you to modify the status code used for temporal redirects.`,
|
||||
},
|
||||
permanentRedirectAnnotation: {
|
||||
Validator: parser.ValidateRegex(parser.URLIsValidRegex, false),
|
||||
Scope: parser.AnnotationScopeLocation,
|
||||
|
|
@ -105,13 +115,22 @@ func (r redirect) Parse(ing *networking.Ingress) (interface{}, error) {
|
|||
}
|
||||
|
||||
if tr != "" {
|
||||
trc, err := parser.GetIntAnnotation(temporalRedirectAnnotationCode, ing, r.annotationConfig.Annotations)
|
||||
if err != nil && !errors.IsMissingAnnotations(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if trc < http.StatusMultipleChoices || trc > http.StatusTemporaryRedirect {
|
||||
trc = defaultTemporalRedirectCode
|
||||
}
|
||||
|
||||
if err := isValidURL(tr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Config{
|
||||
URL: tr,
|
||||
Code: http.StatusFound,
|
||||
Code: trc,
|
||||
FromToWWW: r3w,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ func TestPermanentRedirectWithCustomCode(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTemporalRedirect(t *testing.T) {
|
||||
func TestTemporalRedirectWithDefaultCode(t *testing.T) {
|
||||
rp := NewParser(resolver.Mock{})
|
||||
if rp == nil {
|
||||
t.Fatalf("Expected a parser.IngressAnnotation but returned nil")
|
||||
|
|
@ -128,10 +128,49 @@ func TestTemporalRedirect(t *testing.T) {
|
|||
t.Errorf("Expected %v as redirect but returned %s", defRedirectURL, redirect.URL)
|
||||
}
|
||||
if redirect.Code != http.StatusFound {
|
||||
t.Errorf("Expected %v as redirect to have a code %d but had %d", defRedirectURL, defaultPermanentRedirectCode, redirect.Code)
|
||||
t.Errorf("Expected %v as redirect to have a code %d but had %d", defRedirectURL, http.StatusFound, redirect.Code)
|
||||
}
|
||||
if redirect.FromToWWW != true {
|
||||
t.Errorf("Expected %v as redirect to have from-to-www as %v but got %v", defRedirectURL, true, redirect.FromToWWW)
|
||||
}
|
||||
|
||||
func TestTemporalRedirectWithCustomCode(t *testing.T) {
|
||||
rp := NewParser(resolver.Mock{})
|
||||
if rp == nil {
|
||||
t.Fatalf("Expected a parser.IngressAnnotation but returned nil")
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
input int
|
||||
expectOutput int
|
||||
}{
|
||||
"valid code": {http.StatusTemporaryRedirect, http.StatusTemporaryRedirect},
|
||||
"invalid code": {http.StatusTeapot, http.StatusFound},
|
||||
}
|
||||
|
||||
for n, tc := range testCases {
|
||||
t.Run(n, func(t *testing.T) {
|
||||
ing := new(networking.Ingress)
|
||||
|
||||
data := make(map[string]string, 2)
|
||||
data[parser.GetAnnotationWithPrefix(fromToWWWRedirAnnotation)] = "true"
|
||||
data[parser.GetAnnotationWithPrefix(temporalRedirectAnnotation)] = defRedirectURL
|
||||
data[parser.GetAnnotationWithPrefix(temporalRedirectAnnotationCode)] = strconv.Itoa(tc.input)
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := rp.Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error with ingress: %v", err)
|
||||
}
|
||||
redirect, ok := i.(*Config)
|
||||
if !ok {
|
||||
t.Errorf("Expected a Redirect type")
|
||||
}
|
||||
if redirect.URL != defRedirectURL {
|
||||
t.Errorf("Expected %v as redirect but returned %s", defRedirectURL, redirect.URL)
|
||||
}
|
||||
if redirect.Code != tc.expectOutput {
|
||||
t.Errorf("Expected %v as redirect to have a code %d but had %d", defRedirectURL, tc.expectOutput, redirect.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue