mirror of
https://github.com/alibaba/higress.git
synced 2026-05-29 15:17:27 +08:00
Add ingress (#18)
This commit is contained in:
152
ingress/kube/annotations/redirect.go
Normal file
152
ingress/kube/annotations/redirect.go
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// 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 annotations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
)
|
||||
|
||||
const (
|
||||
appRoot = "app-root"
|
||||
temporalRedirect = "temporal-redirect"
|
||||
permanentRedirect = "permanent-redirect"
|
||||
permanentRedirectCode = "permanent-redirect-code"
|
||||
sslRedirect = "ssl-redirect"
|
||||
forceSSLRedirect = "force-ssl-redirect"
|
||||
|
||||
defaultPermanentRedirectCode = 301
|
||||
defaultTemporalRedirectCode = 302
|
||||
)
|
||||
|
||||
var (
|
||||
_ Parser = &redirect{}
|
||||
_ RouteHandler = &redirect{}
|
||||
)
|
||||
|
||||
type RedirectConfig struct {
|
||||
AppRoot string
|
||||
|
||||
URL string
|
||||
|
||||
Code int
|
||||
|
||||
httpsRedirect bool
|
||||
}
|
||||
|
||||
type redirect struct{}
|
||||
|
||||
func (r redirect) Parse(annotations Annotations, config *Ingress, _ *GlobalContext) error {
|
||||
if !needRedirectConfig(annotations) {
|
||||
return nil
|
||||
}
|
||||
|
||||
redirectConfig := &RedirectConfig{
|
||||
Code: defaultPermanentRedirectCode,
|
||||
}
|
||||
config.Redirect = redirectConfig
|
||||
|
||||
redirectConfig.AppRoot, _ = annotations.ParseStringASAP(appRoot)
|
||||
|
||||
httpsRedirect, _ := annotations.ParseBoolASAP(sslRedirect)
|
||||
forceHTTPSRedirect, _ := annotations.ParseBoolASAP(forceSSLRedirect)
|
||||
if httpsRedirect || forceHTTPSRedirect {
|
||||
redirectConfig.httpsRedirect = true
|
||||
}
|
||||
|
||||
// temporal redirect is firstly applied.
|
||||
tr, err := annotations.ParseStringASAP(temporalRedirect)
|
||||
if err != nil && !IsMissingAnnotations(err) {
|
||||
return nil
|
||||
}
|
||||
if tr != "" && isValidURL(tr) == nil {
|
||||
redirectConfig.URL = tr
|
||||
redirectConfig.Code = defaultTemporalRedirectCode
|
||||
return nil
|
||||
}
|
||||
|
||||
// permanent redirect
|
||||
// url
|
||||
pr, err := annotations.ParseStringASAP(permanentRedirect)
|
||||
if err != nil && !IsMissingAnnotations(err) {
|
||||
return nil
|
||||
}
|
||||
if pr != "" && isValidURL(pr) == nil {
|
||||
redirectConfig.URL = pr
|
||||
}
|
||||
// code
|
||||
if prc, err := annotations.ParseIntASAP(permanentRedirectCode); err == nil {
|
||||
if prc < http.StatusMultipleChoices || prc > http.StatusPermanentRedirect {
|
||||
prc = defaultPermanentRedirectCode
|
||||
}
|
||||
redirectConfig.Code = prc
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r redirect) ApplyRoute(route *networking.HTTPRoute, config *Ingress) {
|
||||
redirectConfig := config.Redirect
|
||||
if redirectConfig == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var redirectPolicy *networking.HTTPRedirect
|
||||
if redirectConfig.URL != "" {
|
||||
parseURL, err := url.Parse(redirectConfig.URL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
redirectPolicy = &networking.HTTPRedirect{
|
||||
Scheme: parseURL.Scheme,
|
||||
Authority: parseURL.Host,
|
||||
Uri: parseURL.Path,
|
||||
RedirectCode: uint32(redirectConfig.Code),
|
||||
}
|
||||
} else if redirectConfig.httpsRedirect {
|
||||
redirectPolicy = &networking.HTTPRedirect{
|
||||
Scheme: "https",
|
||||
// 308 is the default code for ssl redirect
|
||||
RedirectCode: 308,
|
||||
}
|
||||
}
|
||||
|
||||
route.Redirect = redirectPolicy
|
||||
}
|
||||
|
||||
func needRedirectConfig(annotations Annotations) bool {
|
||||
return annotations.HasASAP(temporalRedirect) ||
|
||||
annotations.HasASAP(permanentRedirect) ||
|
||||
annotations.HasASAP(sslRedirect) ||
|
||||
annotations.HasASAP(forceSSLRedirect) ||
|
||||
annotations.HasASAP(appRoot)
|
||||
}
|
||||
|
||||
func isValidURL(s string) error {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(u.Scheme, "http") {
|
||||
return fmt.Errorf("only http and https are valid protocols (%v)", u.Scheme)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user