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: correctly support timeout #299

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 42 additions & 13 deletions TencentCloud/Common/Http/HttpConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,51 @@ public class HttpConnection
{
private class HttpClientHolder
{
private static readonly ConcurrentDictionary<string, HttpClientHolder> httpclients =
new ConcurrentDictionary<string, HttpClientHolder>();
private struct CacheKey : IEquatable<CacheKey>
{
public string Proxy;
public int Timeout;

public CacheKey(string proxy, int timeout)
{
Proxy = string.IsNullOrEmpty(proxy) ? "" : proxy;
Timeout = timeout;
}

public bool Equals(CacheKey other)
{
return Proxy == other.Proxy && Timeout == other.Timeout;
}

public override bool Equals(object obj)
{
return obj is CacheKey other && Equals(other);
}

public override int GetHashCode()
{
unchecked
{
return ((Proxy != null ? Proxy.GetHashCode() : 0) * 397) ^ Timeout;
}
}
}

private static readonly ConcurrentDictionary<CacheKey, HttpClientHolder> httpclients =
new ConcurrentDictionary<CacheKey, HttpClientHolder>();

public static HttpClient GetClient(string proxy)
public static HttpClient GetClient(string proxy, int timeout)
{
string key = string.IsNullOrEmpty(proxy) ? "" : proxy;
HttpClientHolder result = httpclients.GetOrAdd(key, (k) => { return new HttpClientHolder(k); });
CacheKey key = new CacheKey(proxy, timeout);
HttpClientHolder result = httpclients.GetOrAdd(key, (k) => { return new HttpClientHolder(key); });
TimeSpan timeSpan = DateTime.Now - result.createTime;

// A new connection is created every 5 minutes
// and old connections are discarded to avoid DNS flushing issues.
while (timeSpan.TotalSeconds > 300)
{
ICollection<KeyValuePair<string, HttpClientHolder>> kv = httpclients;
kv.Remove(new KeyValuePair<string, HttpClientHolder>(key, result));
ICollection<KeyValuePair<CacheKey, HttpClientHolder>> kv = httpclients;
kv.Remove(new KeyValuePair<CacheKey, HttpClientHolder>(key, result));
result = httpclients.GetOrAdd(key, (k) => { return new HttpClientHolder(k); });
timeSpan = DateTime.Now - result.createTime;
}
Expand All @@ -56,24 +86,23 @@ public static HttpClient GetClient(string proxy)

public readonly DateTime createTime;

public HttpClientHolder(string proxy)
private HttpClientHolder(CacheKey key)
{
string p = string.IsNullOrEmpty(proxy) ? "" : proxy;
if (p == "")
if (string.IsNullOrEmpty(key.Proxy))
{
this.client = new HttpClient();
}
else
{
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy(proxy),
Proxy = new WebProxy(key.Proxy),
};

this.client = new HttpClient(handler: httpClientHandler, disposeHandler: true);
}

this.client.Timeout = TimeSpan.FromSeconds(60);
this.client.Timeout = TimeSpan.FromSeconds(key.Timeout);
this.createTime = DateTime.Now;
}
}
Expand All @@ -97,7 +126,7 @@ public HttpConnection(string baseUrl, int timeout, string proxy, HttpClient http
}
else
{
this.http = HttpClientHolder.GetClient(this.proxy);
this.http = HttpClientHolder.GetClient(this.proxy, this.timeout);
}
}

Expand Down