fix: no need for idna conversion in domain validator

This commit is contained in:
Stavros
2026-08-23 00:58:11 +03:00
parent 61d372b288
commit 8614f8768b
4 changed files with 20 additions and 66 deletions
+10 -1
View File
@@ -38,7 +38,16 @@ func SafeParseAppURL(str string) (string, error) {
return "", fmt.Errorf("ip addresses not allowed")
}
hostname, err = idna.Lookup.ToASCII(hostname)
i := idna.New(
idna.MapForLookup(),
idna.Transitional(false),
idna.BidiRule(),
idna.StrictDomainName(false),
idna.CheckHyphens(true),
idna.CheckJoiners(false),
)
hostname, err = i.ToASCII(hostname)
if err != nil {
return "", fmt.Errorf("failed to convert hostname to ascii: %w", err)
+8 -1
View File
@@ -43,6 +43,13 @@ func TestSafeParseAPPURL(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, expected, result)
// Underscores
appURL = "http://sub_tinyauth.app"
expected = "http://sub_tinyauth.app"
result, err = utils.SafeParseAppURL(appURL)
assert.NoError(t, err)
assert.Equal(t, expected, result)
// Lowercase
appURL = "HTTP://SUb.tinyAUth.aPP"
expected = "http://sub.tinyauth.app"
@@ -66,7 +73,7 @@ func TestSafeParseAPPURL(t *testing.T) {
assert.ErrorContains(t, err, "invalid url")
// Invalid punycode
appURL = "http://ab--cd.example.com"
appURL = "http://xn--h-kva.example.com"
_, err = utils.SafeParseAppURL(appURL)
assert.ErrorContains(t, err, "failed to convert hostname to ascii")
+2 -16
View File
@@ -11,8 +11,6 @@ import (
"net"
"net/url"
"strings"
"golang.org/x/net/idna"
)
// Errors
@@ -114,23 +112,11 @@ func (v *DomainValidator) getURL(i string) (*url.URL, error) {
}
func (v *DomainValidator) getHostname(hostname string) (string, error) {
hostname = strings.ToLower(hostname)
hostname = strings.TrimSuffix(hostname, ".")
if net.ParseIP(hostname) != nil {
return "", fmt.Errorf("ip addresses are not supported")
}
i := idna.New(
idna.MapForLookup(),
idna.Transitional(false),
idna.BidiRule(),
idna.StrictDomainName(false),
idna.CheckHyphens(false),
idna.CheckJoiners(false),
)
hostname, err := i.ToASCII(hostname)
if err != nil {
return "", fmt.Errorf("failed to convert hostname to ascii: %w", err)
}
hostname = strings.ToLower(hostname)
hostname = strings.TrimSuffix(hostname, ".")
return hostname, nil
}
-48
View File
@@ -50,16 +50,6 @@ func TestDomainValidator_SafeHostname(t *testing.T) {
input: "https://example.com",
expected: "example.com",
},
{
description: "Domain with underscores should pass",
input: "https://my_domain.com",
expected: "my_domain.com",
},
{
description: "Domain with leading hyphen should pass",
input: "https://-my-domain.com",
expected: "-my-domain.com",
},
{
description: "Domain without scheme should parse if scheme is disabled",
input: "example.com",
@@ -111,18 +101,6 @@ func TestDomainValidator_SafeHostname(t *testing.T) {
assert.ErrorContains(t, e, "ip addresses are not supported")
},
},
{
description: "Domains with unicode characters should be allowed",
input: "bücher.example.com",
expected: "xn--bcher-kva.example.com",
},
{
description: "Invalid IDNA domain should fail",
input: "xn--r-kva.example.com",
errorFunc: func(t *testing.T, e error) {
assert.ErrorContains(t, e, "invalid label")
},
},
{
description: "With port enabled without any port should work",
options: DomainValidatorOptions{WithPort: true},
@@ -204,22 +182,6 @@ func TestDomainValidator_Validate(t *testing.T) {
expected: "https://example.com:443",
actual: "https://example.com:443",
},
{
description: "Failure to format expected domain should fail",
expected: "xn--r-kva.example.com",
actual: "example.com",
errorFunc: func(t *testing.T, e error) {
assert.ErrorContains(t, e, "idna: invalid label")
},
},
{
description: "Failure to format check domain should fail",
expected: "example.com",
actual: "xn--r-kva.example.com",
errorFunc: func(t *testing.T, e error) {
assert.ErrorContains(t, e, "idna: invalid label")
},
},
{
description: "Valid domains with matching schemes and ports should pass",
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https", "http"}, WithPort: true},
@@ -246,16 +208,6 @@ func TestDomainValidator_Validate(t *testing.T) {
actual: "example.com",
expected: "example.com",
},
{
description: "Unicode valid domains should pass",
expected: "xn--bcher-kva.example.com",
actual: "bücher.example.com",
},
{
description: "Unicode valid domains should pass (reverse)",
expected: "bücher.example.com",
actual: "xn--bcher-kva.example.com",
},
{
description: "Non matching hostnames should fail",
expected: "example.com",