AI Gateway Go 0.10.0 源码快照 + 旗舰版需求规划报告
M0-M7 已完成:核心网关(身份/RBAC/TOTP/OIDC/SAML/Provider/配额/路由/内容策略/审计/定价)+ 资源市场(MCP/Skills/数字员工)。 含 22 个 PostgreSQL 迁移、管理端/门户端前端源码、OpenAPI 契约、部署 compose。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ValidateBaseURL(ctx context.Context, raw string, allowPrivate bool) (string, error) {
|
||||
parsed, err := url.Parse(strings.TrimSpace(raw))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if (parsed.Scheme != "http" && parsed.Scheme != "https") || parsed.Hostname() == "" {
|
||||
return "", errors.New("base_url must be an absolute http(s) URL")
|
||||
}
|
||||
if parsed.User != nil || parsed.RawQuery != "" || parsed.Fragment != "" {
|
||||
return "", errors.New("base_url must not contain user info, query, or fragment")
|
||||
}
|
||||
if !allowPrivate {
|
||||
addresses, err := net.DefaultResolver.LookupIPAddr(ctx, parsed.Hostname())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve base_url host: %w", err)
|
||||
}
|
||||
if len(addresses) == 0 {
|
||||
return "", errors.New("base_url host did not resolve")
|
||||
}
|
||||
for _, address := range addresses {
|
||||
if !isPublicAddress(address.IP) {
|
||||
return "", fmt.Errorf("base_url resolves to blocked address %s", address.IP)
|
||||
}
|
||||
}
|
||||
}
|
||||
parsed.Path = strings.TrimRight(parsed.Path, "/")
|
||||
return parsed.String(), nil
|
||||
}
|
||||
|
||||
func isPublicAddress(ip net.IP) bool {
|
||||
return ip != nil && !ip.IsPrivate() && !ip.IsLoopback() && !ip.IsLinkLocalUnicast() &&
|
||||
!ip.IsLinkLocalMulticast() && !ip.IsMulticast() && !ip.IsUnspecified()
|
||||
}
|
||||
Reference in New Issue
Block a user