diff --git a/client.go b/client.go index 820e4c3..1642e96 100644 --- a/client.go +++ b/client.go @@ -42,7 +42,21 @@ func (c *Client) Get(url string) (*Response, error) { // Do performs a Gemini request and returns a Gemini response. func (c *Client) Do(req *Request) (*Response, error) { - // Extract hostname + // Punycode request URL + if punycode, err := punycodeHost(req.URL.Host); err != nil { + return nil, err + } else { + // Make a copy of the request + _req := *req + req = &_req + _url := *req.URL + req.URL = &_url + + // Set the host + req.URL.Host = punycode + } + + // Extract hostname and punycode it hostname, port, err := net.SplitHostPort(req.Host) if err != nil { return nil, err diff --git a/punycode.go b/punycode.go index 565790c..cf0ecb4 100644 --- a/punycode.go +++ b/punycode.go @@ -16,6 +16,7 @@ func isASCII(s string) bool { return true } +// punycodeHostname returns the punycoded version of hostname. func punycodeHostname(hostname string) (string, error) { if net.ParseIP(hostname) != nil { return hostname, nil @@ -25,3 +26,21 @@ func punycodeHostname(hostname string) (string, error) { } return idna.Lookup.ToASCII(hostname) } + +// punycodeHost returns the punycoded version of host. +// host may contain a port. +func punycodeHost(host string) (string, error) { + hostname, port, err := net.SplitHostPort(host) + if err != nil { + hostname = host + port = "" + } + hostname, err = punycodeHostname(hostname) + if err != nil { + return "", err + } + if port == "" { + return hostname, nil + } + return net.JoinHostPort(hostname, port), nil +}