Package idna implements IDNA2008 using the compatibility processing defined by UTS (Unicode Technical Standard) #46, which defines a standard to deal with the transition from IDNA2003.
IDNA2008 (Internationalized Domain Names for Applications) is defined in RFC 5890, RFC 5891, RFC 5892, RFC 5893 and RFC 5894.
import "golang.org/x/net/idna"// UnicodeVersion is the Unicode version from which the tables in this package are derived
const UnicodeVersion = "15.0.0"var (
// Punycode is a Profile that does raw punycode processing with minimal validation
Punycode *Profile = punycode
// Lookup is the recommended profile for looking up domain names (RFC 5891 Section 5)
Lookup *Profile = lookup
// Display is the recommended profile for displaying domain names
Display *Profile = display
// Registration is the recommended profile for checking whether an IDN is valid for registration
Registration *Profile = registration
)// New creates a new Profile
func New(o ...Option) *Profile
// ToASCII is a wrapper for Punycode.ToASCII
func ToASCII(s string) (string, error)
// ToUnicode is a wrapper for Punycode.ToUnicode
func ToUnicode(s string) (string, error)// Profile defines the configuration of an IDNA mapper
type Profile struct {
// Has unexported fields
}
func (p *Profile) String() string
func (p *Profile) ToASCII(s string) (string, error)
func (p *Profile) ToUnicode(s string) (string, error)// Option configures a Profile at creation time
type Option func(*options)
// BidiRule enables the Bidi rule as defined in RFC 5893
func BidiRule() Option
// CheckHyphens sets whether to check for correct use of hyphens in labels
func CheckHyphens(enable bool) Option
// CheckJoiners sets whether to check the ContextJ rules (RFC 5892 Appendix A)
func CheckJoiners(enable bool) Option
// MapForLookup sets validation and mapping options for domain name lookup
func MapForLookup() Option
// RemoveLeadingDots removes leading label separators
func RemoveLeadingDots(remove bool) Option
// StrictDomainName limits the set of permissible ASCII characters
func StrictDomainName(use bool) Option
// Transitional sets a Profile to use the Transitional mapping
func Transitional(transitional bool) Option
// ValidateForRegistration sets validation options for registration
func ValidateForRegistration() Option
// ValidateLabels sets whether to check the mandatory label validation criteria
func ValidateLabels(enable bool) Option
// VerifyDNSLength sets whether a Profile should fail if any IDN parts are too long
func VerifyDNSLength(verify bool) Optionimport (
"fmt"
"golang.org/x/net/idna"
)
func convertDomain() {
// Convert Unicode domain to ASCII (Punycode)
ascii, err := idna.ToASCII("münchen.de")
if err != nil {
panic(err)
}
fmt.Println("ASCII:", ascii) // "xn--mnchen-3ya.de"
// Convert ASCII (Punycode) to Unicode
unicode, err := idna.ToUnicode("xn--mnchen-3ya.de")
if err != nil {
panic(err)
}
fmt.Println("Unicode:", unicode) // "münchen.de"
}func lookupDomain(domain string) error {
// Use Lookup profile for domain name resolution
ascii, err := idna.Lookup.ToASCII(domain)
if err != nil {
return fmt.Errorf("invalid domain: %w", err)
}
fmt.Printf("Lookup domain: %s\n", ascii)
// Perform DNS lookup with ASCII domain
// ...
return nil
}
func displayDomain(domain string) (string, error) {
// Use Display profile for showing domains to users
displayName, err := idna.Display.ToUnicode(domain)
if err != nil {
return "", err
}
return displayName, nil
}func validateForRegistration(domain string) error {
// Use Registration profile to check if domain is valid for registration
_, err := idna.Registration.ToASCII(domain)
if err != nil {
return fmt.Errorf("domain not valid for registration: %w", err)
}
return nil
}import (
"golang.org/x/net/idna"
"net/http"
"net/url"
)
func makeRequest(unicodeDomain, path string) error {
// Convert Unicode domain to ASCII for HTTP request
asciiDomain, err := idna.ToASCII(unicodeDomain)
if err != nil {
return err
}
// Build URL with ASCII domain
u := &url.URL{
Scheme: "https",
Host: asciiDomain,
Path: path,
}
resp, err := http.Get(u.String())
if err != nil {
return err
}
defer resp.Body.Close()
// Process response...
return nil
}
// Usage:
// makeRequest("münchen.de", "/index.html")func validateWithBidiRule(domain string) error {
// Create profile with Bidi rule for proper validation
profile := idna.New(
idna.MapForLookup(),
idna.BidiRule(),
)
_, err := profile.ToASCII(domain)
if err != nil {
return fmt.Errorf("domain fails Bidi validation: %w", err)
}
return nil
}func normalizeURL(rawURL string) (string, error) {
u, err := url.Parse(rawURL)
if err != nil {
return "", err
}
// Convert host to ASCII form
if u.Host != "" {
asciiHost, err := idna.ToASCII(u.Host)
if err != nil {
return "", fmt.Errorf("invalid host: %w", err)
}
u.Host = asciiHost
}
return u.String(), nil
}
// Usage:
// normalized, err := normalizeURL("https://münchen.de/path")
// Result: "https://xn--mnchen-3ya.de/path"