Files
waf-platform/EdgeAdmin/internal/web/actions/default/httpdns/sandbox/test.go
2026-02-24 11:33:44 +08:00

164 lines
4.1 KiB
Go

package sandbox
import (
"encoding/json"
"fmt"
"net"
"net/url"
"strconv"
"strings"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/iwind/TeaGo/maps"
)
type TestAction struct {
actionutils.ParentAction
}
func (this *TestAction) RunPost(params struct {
AppId string
Domain string
ClientIp string
Qtype string
SDNSParamsJSON string
}) {
if len(params.ClientIp) == 0 {
params.ClientIp = "203.0.113.100"
}
params.SDNSParamsJSON = strings.TrimSpace(params.SDNSParamsJSON)
sdnsParams, err := parseSDNSParamsJSON(params.SDNSParamsJSON)
if err != nil {
this.Fail(err.Error())
return
}
clientSubnet := this.maskSubnet(params.ClientIp, 24, 56)
if len(clientSubnet) == 0 {
clientSubnet = "203.0.113.0/24"
}
sniPolicy := "empty"
publicSNI := ""
ecsMode := "off"
ecsIPv4Prefix := 24
ecsIPv6Prefix := 56
pinningMode := "off"
sanMode := "off"
query := url.Values{}
query.Set("appId", params.AppId)
query.Set("dn", params.Domain)
query.Set("cip", params.ClientIp)
query.Set("qtype", params.Qtype)
for _, item := range sdnsParams {
query.Add("sdns_"+item.GetString("name"), item.GetString("value"))
}
requestURL := "https://api.httpdns.example.com/resolve?" + query.Encode()
this.Data["result"] = maps.Map{
"code": 0,
"message": "ok (mock)",
"requestId": "mock-rid-20260221-001",
"data": maps.Map{
"request_url": requestURL,
"client_ip": params.ClientIp,
"client_region": "中国, 上海, 上海",
"line_name": "默认线路",
"sdns_params": sdnsParams,
"ips": []string{"203.0.113.10", "203.0.113.11"},
"records": []maps.Map{
{
"domain": params.Domain,
"type": params.Qtype,
"ip": "203.0.113.10",
"ttl": 30,
"region": "中国-上海-上海",
"line": "默认线路",
},
{
"domain": params.Domain,
"type": params.Qtype,
"ip": "203.0.113.11",
"ttl": 30,
"region": "中国-上海-上海",
"line": "默认线路",
},
},
"ttl": 30,
"sni_policy": sniPolicy,
"public_sni": publicSNI,
"client_subnet": clientSubnet,
"ecs_mode": ecsMode,
"ecs_ipv4_prefix": ecsIPv4Prefix,
"ecs_ipv6_prefix": ecsIPv6Prefix,
"pinning_mode": pinningMode,
"san_mode": sanMode,
"fingerprint_algo": "sha256",
"cert_fingerprints": []string{"8f41ab8d32fca7f9a2b0fdd09a0e2ccf31e5579cd3a0b65f1a9f2f2ec8f38d4a"},
"verify_headers": maps.Map{
"X-Edge-Resolve-AppId": params.AppId,
"X-Edge-Resolve-Expire": "1768953600",
"X-Edge-Resolve-Nonce": "mock-nonce-123456",
"X-Edge-Resolve-Target": params.Domain,
"X-Edge-Resolve-Sign": "mock-signature-base64url",
},
},
}
this.Success()
}
func parseSDNSParamsJSON(raw string) ([]maps.Map, error) {
if len(raw) == 0 {
return []maps.Map{}, nil
}
list := []maps.Map{}
if err := json.Unmarshal([]byte(raw), &list); err != nil {
return nil, err
}
if len(list) > 10 {
return nil, fmt.Errorf("sdns params should be <= 10")
}
result := make([]maps.Map, 0, len(list))
for _, item := range list {
name := strings.TrimSpace(item.GetString("name"))
value := strings.TrimSpace(item.GetString("value"))
if len(name) == 0 && len(value) == 0 {
continue
}
if len(name) == 0 || len(name) > 64 {
return nil, fmt.Errorf("sdns param name should be in 1-64")
}
if len(value) == 0 || len(value) > 64 {
return nil, fmt.Errorf("sdns param value should be in 1-64")
}
result = append(result, maps.Map{
"name": name,
"value": value,
})
}
if len(result) > 10 {
return nil, fmt.Errorf("sdns params should be <= 10")
}
return result, nil
}
func (this *TestAction) maskSubnet(ip string, ipv4Prefix int, ipv6Prefix int) string {
parsed := net.ParseIP(ip)
if parsed == nil {
return ""
}
ipv4 := parsed.To4()
if ipv4 != nil {
mask := net.CIDRMask(ipv4Prefix, 32)
return ipv4.Mask(mask).String() + "/" + strconv.Itoa(ipv4Prefix)
}
mask := net.CIDRMask(ipv6Prefix, 128)
return parsed.Mask(mask).String() + "/" + strconv.Itoa(ipv6Prefix)
}