mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-30 06:16:37 +08:00
171 lines
4.3 KiB
Go
171 lines
4.3 KiB
Go
package service
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
func normalizeOriginAddress(raw string) string {
|
|
return strings.ToLower(strings.TrimSpace(raw))
|
|
}
|
|
|
|
func validateOriginAddress(address string) error {
|
|
if address == "" {
|
|
return errors.New("源站地址不能为空")
|
|
}
|
|
if strings.Contains(address, "://") || strings.ContainsAny(address, "/?#") {
|
|
return errors.New("源站地址格式不合法")
|
|
}
|
|
if strings.HasPrefix(address, "[") || strings.HasSuffix(address, "]") {
|
|
return errors.New("源站地址无需包含 IPv6 方括号")
|
|
}
|
|
if ip := net.ParseIP(address); ip != nil {
|
|
return nil
|
|
}
|
|
if len(address) > 253 {
|
|
return errors.New("源站地址格式不合法")
|
|
}
|
|
labels := strings.Split(address, ".")
|
|
for _, label := range labels {
|
|
if len(label) == 0 || len(label) > 63 {
|
|
return errors.New("源站地址格式不合法")
|
|
}
|
|
if label[0] == '-' || label[len(label)-1] == '-' {
|
|
return errors.New("源站地址格式不合法")
|
|
}
|
|
for _, r := range label {
|
|
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '-' {
|
|
continue
|
|
}
|
|
return errors.New("源站地址格式不合法")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func normalizeOriginName(name string, address string) string {
|
|
normalized := strings.TrimSpace(name)
|
|
if normalized != "" {
|
|
return normalized
|
|
}
|
|
return address
|
|
}
|
|
|
|
func normalizeOriginPort(raw string) (string, error) {
|
|
port := strings.TrimSpace(raw)
|
|
if port == "" {
|
|
return "", errors.New("端口不能为空")
|
|
}
|
|
value, err := strconv.Atoi(port)
|
|
if err != nil || value < 1 || value > 65535 {
|
|
return "", errors.New("端口格式不合法")
|
|
}
|
|
return strconv.Itoa(value), nil
|
|
}
|
|
|
|
func normalizeOriginScheme(raw string) (string, error) {
|
|
scheme := strings.ToLower(strings.TrimSpace(raw))
|
|
switch scheme {
|
|
case "http", "https":
|
|
return scheme, nil
|
|
default:
|
|
return "", errors.New("源站协议仅支持 http 或 https")
|
|
}
|
|
}
|
|
|
|
func normalizeOriginURI(raw string) (string, error) {
|
|
uri := strings.TrimSpace(raw)
|
|
if uri == "" {
|
|
return "", nil
|
|
}
|
|
if strings.Contains(uri, "://") {
|
|
return "", errors.New("源站路径不能包含协议")
|
|
}
|
|
if !strings.HasPrefix(uri, "/") && !strings.HasPrefix(uri, "?") {
|
|
return "", errors.New("源站路径需以 / 或 ? 开头")
|
|
}
|
|
return uri, nil
|
|
}
|
|
|
|
func formatOriginHost(address string, port string) string {
|
|
if ip := net.ParseIP(address); ip != nil && strings.Contains(address, ":") {
|
|
return net.JoinHostPort(address, port)
|
|
}
|
|
return net.JoinHostPort(address, port)
|
|
}
|
|
|
|
func buildOriginURLFromParts(
|
|
scheme string,
|
|
address string,
|
|
port string,
|
|
uri string,
|
|
) (string, error) {
|
|
normalizedScheme, err := normalizeOriginScheme(scheme)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
normalizedAddress := normalizeOriginAddress(address)
|
|
if err := validateOriginAddress(normalizedAddress); err != nil {
|
|
return "", err
|
|
}
|
|
normalizedPort, err := normalizeOriginPort(port)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
normalizedURI, err := normalizeOriginURI(uri)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
parsed := &url.URL{
|
|
Scheme: normalizedScheme,
|
|
Host: formatOriginHost(normalizedAddress, normalizedPort),
|
|
}
|
|
if normalizedURI != "" {
|
|
if strings.HasPrefix(normalizedURI, "?") {
|
|
parsed.RawQuery = strings.TrimPrefix(normalizedURI, "?")
|
|
} else {
|
|
pathQuery := strings.SplitN(normalizedURI, "?", 2)
|
|
parsed.Path = pathQuery[0]
|
|
if len(pathQuery) > 1 {
|
|
parsed.RawQuery = pathQuery[1]
|
|
}
|
|
}
|
|
}
|
|
return parsed.String(), nil
|
|
}
|
|
|
|
func extractOriginAddress(rawURL string) (string, error) {
|
|
parsed, err := url.ParseRequestURI(strings.TrimSpace(rawURL))
|
|
if err != nil {
|
|
return "", fmt.Errorf("源站地址格式不合法: %w", err)
|
|
}
|
|
address := normalizeOriginAddress(parsed.Hostname())
|
|
if err := validateOriginAddress(address); err != nil {
|
|
return "", err
|
|
}
|
|
return address, nil
|
|
}
|
|
|
|
func rewriteOriginURLAddress(rawURL string, newAddress string) (string, error) {
|
|
parsed, err := url.ParseRequestURI(strings.TrimSpace(rawURL))
|
|
if err != nil {
|
|
return "", fmt.Errorf("源站地址格式不合法: %w", err)
|
|
}
|
|
address := normalizeOriginAddress(newAddress)
|
|
if err := validateOriginAddress(address); err != nil {
|
|
return "", err
|
|
}
|
|
port := parsed.Port()
|
|
if port == "" {
|
|
return "", errors.New("源站地址缺少端口")
|
|
}
|
|
parsed.Host = formatOriginHost(address, port)
|
|
return parsed.String(), nil
|
|
}
|