mirror of
https://github.com/kubesphere/kubekey.git
synced 2025-12-25 17:12:50 +00:00
Signed-off-by: joyceliu <joyceliu@yunify.com> Co-authored-by: joyceliu <joyceliu@yunify.com>
108 lines
3.3 KiB
Go
108 lines
3.3 KiB
Go
/*
|
|
Copyright 2024 The KubeSphere Authors.
|
|
|
|
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 proxy
|
|
|
|
// Copyright 2013 Ernest Micklei. All rights reserved.
|
|
// Use of this source code is governed by a license
|
|
// that can be found in the LICENSE file.
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/cockroachdb/errors"
|
|
)
|
|
|
|
// PathExpression holds a compiled path expression (RegExp) needed to match against
|
|
// Http request paths and to extract path parameter values.
|
|
type pathExpression struct {
|
|
LiteralCount int // the number of literal characters (means those not resulting from template variable substitution)
|
|
VarNames []string // the names of parameters (enclosed by {}) in the path
|
|
VarCount int // the number of named parameters (enclosed by {}) in the path
|
|
Matcher *regexp.Regexp
|
|
Source string // Path as defined by the RouteBuilder
|
|
tokens []string
|
|
}
|
|
|
|
// NewPathExpression creates a PathExpression from the input URL path.
|
|
// Returns an error if the path is invalid.
|
|
func newPathExpression(path string) (*pathExpression, error) {
|
|
expression, literalCount, varNames, varCount, tokens := templateToRegularExpression(path)
|
|
compiled, err := regexp.Compile(expression)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to compile regexp")
|
|
}
|
|
|
|
return &pathExpression{literalCount, varNames, varCount, compiled, expression, tokens}, nil
|
|
}
|
|
|
|
// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-370003.7.3
|
|
func templateToRegularExpression(template string) (string, int, []string, int, []string) {
|
|
var (
|
|
literalCount int
|
|
varNames []string
|
|
varCount int
|
|
)
|
|
var buffer bytes.Buffer
|
|
buffer.WriteString("^")
|
|
tokens := tokenizePath(template)
|
|
for _, each := range tokens {
|
|
if each == "" {
|
|
continue
|
|
}
|
|
buffer.WriteString("/")
|
|
if strings.HasPrefix(each, "{") {
|
|
// check for regular expression in variable
|
|
colon := strings.Index(each, ":")
|
|
var varName string
|
|
if colon != -1 {
|
|
// extract expression
|
|
varName = strings.TrimSpace(each[1:colon])
|
|
paramExpr := strings.TrimSpace(each[colon+1 : len(each)-1])
|
|
if paramExpr == "*" { // special case
|
|
buffer.WriteString("(.*)")
|
|
} else {
|
|
buffer.WriteString(fmt.Sprintf("(%s)", paramExpr)) // between colon and closing moustache
|
|
}
|
|
} else {
|
|
// plain var
|
|
varName = strings.TrimSpace(each[1 : len(each)-1])
|
|
buffer.WriteString("([^/]+?)")
|
|
}
|
|
varNames = append(varNames, varName)
|
|
varCount++
|
|
} else {
|
|
literalCount += len(each)
|
|
encoded := each
|
|
buffer.WriteString(regexp.QuoteMeta(encoded))
|
|
}
|
|
}
|
|
|
|
return strings.TrimRight(buffer.String(), "/") + "(/.*)?$", literalCount, varNames, varCount, tokens
|
|
}
|
|
|
|
// Tokenize an URL path using the slash separator ; the result does not have empty tokens
|
|
func tokenizePath(path string) []string {
|
|
if path == "/" {
|
|
return nil
|
|
}
|
|
// 3.9.0
|
|
return strings.Split(strings.Trim(path, "/"), "/")
|
|
}
|