Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SetTimeout not changing the timeout in the underlying Dialer #45

Merged
merged 3 commits into from
Sep 2, 2024

Conversation

jafayer
Copy link
Contributor

@jafayer jafayer commented Aug 29, 2024

This branch solves the dialer timeout issue mentioned in #43 and #37.

It does so by creating a dummy struct hasTimeout which has the Timeout field in its struct, and composes proxy.Dialer. This effectively creates a new struct with one property, Timeout, and one method, Dial.

It then uses this dummy type to assert that the client.Dialer has the Timeout property. If it does, it is now able to set the Timeout property in the actual Dialer. This is all necessary because client uses proxy.Dialer which is a more general interface than net.Dialer and lacks the Timeout method, so Golang does not believe it has the property unless it is specifically asserted that it does.

We could achieve this without creating a new type simply by asserting that client.Dialer is net.Dialer (i.e. if d, ok := c.dialer.(*net.Dialer), but then all Dialers would need to fully implement net.Dialer struct which might be incompatible with some uses of the application.

Indeed, this implementation might not work already for any custom dialers that do not have the Timeout property (see Drawbacks).

Drawbacks

This implementation has a couple of drawbacks. It should probably modify the SetDialer method to also return an error if client.Dialer does not have the Timeout, otherwise it will silently fail to change the timeout if someone is using a custom Dialer that does not implement a Timeout. However, I did not want to change the signature of a method as that is a breaking change, so I leave it to @likexian to determine if that is reasonable.

If this is desired, the implementation would look like

// SetTimeout set query timeout
func (c *Client) SetTimeout(timeout time.Duration) (*Client, error ) {
	if d, ok := c.dialer.(*hasTimeout); ok {
		d.Timeout = timeout
		c.timeout = timeout
		return c, nil
	}
	return nil, fmt.Errorf("whois: dialer does not support timeout")
}

Generally, this is also just a bit of an awkward way to go about fixing this. There are probably cleaner ways to fix the problem (as mentioned in one of the Issues, a context could help), but this is certainly one of the fastest ways to resolve.

I welcome feedback on this change!

@likexian
Copy link
Owner

likexian commented Sep 2, 2024

Hello @jafayer
Thanks for your works!


If you think this repository is helpful, please share it with friends, thanks.

@likexian likexian merged commit 259e6b0 into likexian:master Sep 2, 2024
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants