1
0
Fork 0
mirror of https://git.sr.ht/~adnano/go-gemini synced 2024-05-31 00:16:06 +02:00

Make Request.Host optional

This commit is contained in:
Adnan Maolood 2021-02-14 19:02:34 -05:00
parent 41eec39a1d
commit 46e10da3a8
3 changed files with 36 additions and 42 deletions

View File

@ -59,10 +59,20 @@ func (c *Client) Get(url string) (*Response, error) {
// //
// Generally Get will be used instead of Do. // Generally Get will be used instead of Do.
func (c *Client) Do(req *Request) (*Response, error) { func (c *Client) Do(req *Request) (*Response, error) {
// Punycode request URL // Punycode request URL host
if punycode, err := punycodeHost(req.URL.Host); err != nil { hostname, port, err := net.SplitHostPort(req.URL.Host)
if err != nil {
// Likely no port
hostname = req.URL.Host
port = "1965"
}
punycode, err := punycodeHostname(hostname)
if err != nil {
return nil, err return nil, err
} else { }
if hostname != punycode {
hostname = punycode
// Make a copy of the request // Make a copy of the request
_req := *req _req := *req
req = &_req req = &_req
@ -70,17 +80,21 @@ func (c *Client) Do(req *Request) (*Response, error) {
req.URL = &_url req.URL = &_url
// Set the host // Set the host
req.URL.Host = punycode req.URL.Host = net.JoinHostPort(hostname, port)
} }
// Extract hostname and punycode it // Use request host if provided
hostname, port, err := net.SplitHostPort(req.Host) if req.Host != "" {
if err != nil { hostname, port, err = net.SplitHostPort(req.Host)
return nil, err if err != nil {
} // Port is required
punycode, err := punycodeHostname(hostname) return nil, err
if err != nil { }
return nil, err // Punycode hostname
hostname, err = punycodeHostname(hostname)
if err != nil {
return nil, err
}
} }
// Connect to the host // Connect to the host
@ -96,7 +110,7 @@ func (c *Client) Do(req *Request) (*Response, error) {
VerifyConnection: func(cs tls.ConnectionState) error { VerifyConnection: func(cs tls.ConnectionState) error {
return c.verifyConnection(hostname, punycode, cs) return c.verifyConnection(hostname, punycode, cs)
}, },
ServerName: punycode, ServerName: hostname,
} }
ctx := req.Context ctx := req.Context
@ -109,7 +123,7 @@ func (c *Client) Do(req *Request) (*Response, error) {
Timeout: c.Timeout, Timeout: c.Timeout,
} }
address := net.JoinHostPort(punycode, port) address := net.JoinHostPort(hostname, port)
netConn, err := dialer.DialContext(ctx, "tcp", address) netConn, err := dialer.DialContext(ctx, "tcp", address)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -26,21 +26,3 @@ func punycodeHostname(hostname string) (string, error) {
} }
return idna.Lookup.ToASCII(hostname) 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
}

View File

@ -18,8 +18,12 @@ type Request struct {
// requests) or the URL to access (for client requests). // requests) or the URL to access (for client requests).
URL *url.URL URL *url.URL
// For client requests, Host specifies the server to connect to. // For client requests, Host optionally specifies the server to
// Host must contain a port. // connect to. It must be of the form "host:port".
// If empty, the value of URL.Host is used.
// For international domain names, Host may be in Punycode or
// Unicode form. Use golang.org/x/net/idna to convert it to
// either format if needed.
// This field is ignored by the Gemini server. // This field is ignored by the Gemini server.
Host string Host string
@ -55,7 +59,7 @@ type Request struct {
Context context.Context Context context.Context
} }
// NewRequest returns a new request. The host is inferred from the URL. // NewRequest returns a new request.
// //
// The returned Request is suitable for use with Client.Do. // The returned Request is suitable for use with Client.Do.
func NewRequest(rawurl string) (*Request, error) { func NewRequest(rawurl string) (*Request, error) {
@ -67,18 +71,12 @@ func NewRequest(rawurl string) (*Request, error) {
} }
// NewRequestFromURL returns a new request for the given URL. // NewRequestFromURL returns a new request for the given URL.
// The host is inferred from the URL.
// //
// Callers should be careful that the URL query is properly escaped. // Callers should be careful that the URL query is properly escaped.
// See the documentation for QueryEscape for more information. // See the documentation for QueryEscape for more information.
func NewRequestFromURL(url *url.URL) *Request { func NewRequestFromURL(url *url.URL) *Request {
host := url.Host
if url.Port() == "" {
host += ":1965"
}
return &Request{ return &Request{
URL: url, URL: url,
Host: host,
} }
} }