Skip to content

Commit 9dbf4e3

Browse files
committed
Improve: Tracing System.Net verbose to find httpclient requests bug
* The underlying connection was closed: The connection was closed unexpectedly. * wtf when fiddler proxy exists this bug disappears * so i didn't fix it in commit 4ef4558 Link:
1 parent 0a9b0c6 commit 9dbf4e3

File tree

6 files changed

+233
-74
lines changed

6 files changed

+233
-74
lines changed

WeChatBot.Net.Console/App.config

+43
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,47 @@
33
<startup>
44
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
55
</startup>
6+
<system.diagnostics>
7+
<sources>
8+
<source name="System.Net" tracemode="includehex" maxdatasize="1024">
9+
<listeners>
10+
<add name="System.Net"/>
11+
</listeners>
12+
</source>
13+
<source name="System.Net.Cache">
14+
<listeners>
15+
<add name="System.Net"/>
16+
</listeners>
17+
</source>
18+
<source name="System.Net.Http">
19+
<listeners>
20+
<add name="System.Net"/>
21+
</listeners>
22+
</source>
23+
<source name="System.Net.Sockets">
24+
<listeners>
25+
<add name="System.Net"/>
26+
</listeners>
27+
</source>
28+
<source name="System.Net.WebSockets">
29+
<listeners>
30+
<add name="System.Net"/>
31+
</listeners>
32+
</source>
33+
</sources>
34+
<switches>
35+
<add name="System.Net" value="Verbose"/>
36+
<add name="System.Net.Cache" value="Verbose"/>
37+
<add name="System.Net.Http" value="Verbose"/>
38+
<add name="System.Net.Sockets" value="Verbose"/>
39+
<add name="System.Net.WebSockets" value="Verbose"/>
40+
</switches>
41+
<sharedListeners>
42+
<add name="System.Net"
43+
type="System.Diagnostics.TextWriterTraceListener"
44+
initializeData="C:\\Tracing\\network.log"
45+
/>
46+
</sharedListeners>
47+
<trace autoflush="true"/>
48+
</system.diagnostics>
649
</configuration>

WeChatBot.Net.Tests/App.config

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<configuration>
3+
<system.diagnostics>
4+
<sources>
5+
<source name="System.Net" tracemode="includehex" maxdatasize="1024">
6+
<listeners>
7+
<add name="System.Net"/>
8+
</listeners>
9+
</source>
10+
<source name="System.Net.Cache">
11+
<listeners>
12+
<add name="System.Net"/>
13+
</listeners>
14+
</source>
15+
<source name="System.Net.Http">
16+
<listeners>
17+
<add name="System.Net"/>
18+
</listeners>
19+
</source>
20+
<source name="System.Net.Sockets">
21+
<listeners>
22+
<add name="System.Net"/>
23+
</listeners>
24+
</source>
25+
<source name="System.Net.WebSockets">
26+
<listeners>
27+
<add name="System.Net"/>
28+
</listeners>
29+
</source>
30+
</sources>
31+
<switches>
32+
<add name="System.Net" value="Verbose"/>
33+
<add name="System.Net.Cache" value="Verbose"/>
34+
<add name="System.Net.Http" value="Verbose"/>
35+
<add name="System.Net.Sockets" value="Verbose"/>
36+
<add name="System.Net.WebSockets" value="Verbose"/>
37+
</switches>
38+
<sharedListeners>
39+
<add name="System.Net"
40+
type="System.Diagnostics.TextWriterTraceListener"
41+
initializeData="C:\\Tracing\\network.log"
42+
/>
43+
</sharedListeners>
44+
<trace autoflush="true"/>
45+
</system.diagnostics>
46+
</configuration>

WeChatBot.Net.Tests/ClientTests.cs

+54-74
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Net;
34
using System.Net.Http;
45
using System.Threading;
56
using System.Threading.Tasks;
67
using Flurl.Http;
8+
using Flurl.Http.Configuration;
79
using NUnit.Framework;
810
using WeChatBot.Net.Enums;
911
using WeChatBot.Net.Extensions;
@@ -13,13 +15,6 @@ namespace WeChatBot.Net.Tests
1315
[TestFixture()]
1416
public class ClientTests
1517
{
16-
[Test()]
17-
public async Task GetUuidTest_Normal_ShouldReturnTrue()
18-
{
19-
var q = await new Client().GetUuid();
20-
Assert.IsTrue(q.Item1);
21-
}
22-
2318
[Test()]
2419
[Ignore("manual run this for debug")]
2520
public async Task RunTest_Normal_ShouldOuputQRCode()
@@ -34,12 +29,11 @@ public async Task RunTest_Normal_ShouldOuputQRCode()
3429
Assert.Pass();
3530
}
3631

37-
[Test]
38-
public async Task LoginTest_Https_ShouldReturn400()
32+
[Test()]
33+
public async Task GetUuidTest_Normal_ShouldReturnTrue()
3934
{
40-
var url = @"https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=1&uuid=YenIkE0Lsw==&_=1474877000";
41-
var q = await url.GetAsync();
42-
Assert.That(q.IsSuccessStatusCode);
35+
var q = await new Client().GetUuid();
36+
Assert.IsTrue(q.Item1);
4337
}
4438

4539
[Test]
@@ -50,33 +44,13 @@ public async Task LoginTest_HttpsWithFlurlClient_ShouldReturn400()
5044
Assert.That(q.IsSuccessStatusCode);
5145
}
5246

53-
/// <summary>
54-
/// AutoDispose = false fix this problem
55-
/// </summary>
56-
/// <returns></returns>
57-
[Test]
58-
public async Task LoginTest_HttpsWithFlurlClientTwice_ShouldReturn400()
59-
{
60-
var url = @"https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=1&uuid=YenIkE0Lsw==&_=1474877000";
61-
var flurlClient = new FlurlClient() {AutoDispose = false};
62-
{
63-
var q = await url.WithClient(flurlClient).GetAsyncSafe();
64-
Assert.That(q.IsSuccessStatusCode);
65-
await q.Content.ReadAsStringAsync();
66-
}
67-
{
68-
var q = await url.WithClient(flurlClient).GetAsyncSafe();
69-
Assert.That(q.IsSuccessStatusCode);
70-
}
71-
}
72-
7347
[Category("TestHttpClient")]
7448
[Test]
7549
public async Task LoginTest_HttpsWithHttpClient_ShouldReturn400()
7650
{
7751
using (var cts = new CancellationTokenSource())
7852
{
79-
cts.CancelAfter(TimeSpan.FromSeconds(5));
53+
cts.CancelAfter(TimeSpan.FromSeconds(3));
8054

8155
var url = @"https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=1&uuid=YenIkE0Lsw==&_=1474877000";
8256

@@ -90,53 +64,59 @@ public async Task LoginTest_HttpsWithHttpClient_ShouldReturn400()
9064

9165
[Category("TestHttpClient")]
9266
[Test]
93-
public async Task LoginTest_HttpsWithHttpClientTwice_ShouldReturn400()
67+
public void LoginTest_NewFlurlClientTwice_ShouldReturn400()
9468
{
95-
using (var cts = new CancellationTokenSource())
96-
{
97-
cts.CancelAfter(TimeSpan.FromSeconds(5));
98-
99-
var url = @"https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=1&uuid=YenIkE0Lsw==&_=1474877000"; //a new httpclient will fail
100-
101-
//url = @"https://www.baidu.com"; //uncomment to use this url, r1 r2 r3 both success
102-
103-
var h = new HttpClientHandler()
104-
{
105-
AllowAutoRedirect = true,
106-
Proxy = new WebProxy("http://127.0.0.1:8888"),
107-
UseProxy = true
108-
};
109-
110-
using (var client = new HttpClient(h))
111-
{
112-
client.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
113-
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
114-
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5");
69+
Assert.ThrowsAsync<TaskCanceledException>(async () =>
70+
{
71+
using (var cts = new CancellationTokenSource())
72+
{
73+
cts.CancelAfter(TimeSpan.FromSeconds(3));
74+
75+
var url = @"https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=1&uuid=YenIkE0Lsw==&_=1474877000";
76+
77+
using (var client = new HttpClient())
78+
{
79+
var q = await client.GetAsync(url, cts.Token);
80+
Assert.That(q.IsSuccessStatusCode);
81+
}
82+
83+
var handler = new HttpClientHandler()
84+
{
85+
};
86+
using (var client = new HttpClient(handler))
87+
{
88+
var q = await client.GetAsync(url, cts.Token);
89+
Assert.That(q.IsSuccessStatusCode);
90+
}
91+
}
92+
});
93+
}
11594

116-
var q = await client.GetAsync(url, cts.Token); //first request r1 //success
117-
var q2 = await client.GetAsync(url, cts.Token); //second request r2 //sucess
95+
[Category("TestHttpClient")]
96+
[Test]
97+
public async Task LoginTest_NewFlurlClientTwice2_ShouldReturn400()
98+
{
99+
var url = @"https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=1&uuid=YenIkE0Lsw==&_=1474877000";
100+
//ServicePointManager.SetTcpKeepAlive(false, 1,1);
101+
//System.Net.ServicePointManager.Expect100Continue = false;
102+
//ServicePoint sp = ServicePointManager.FindServicePoint(new Uri(url));
103+
//sp.MaxIdleTime = 1;
104+
//await Task.Delay(TimeSpan.FromMilliseconds(2));
118105

119-
Assert.That(q.IsSuccessStatusCode);
120-
Assert.That(q2.IsSuccessStatusCode);
121-
}
106+
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
107+
var client = new HttpClient();
122108

123-
Console.WriteLine("fuck httpclient");
109+
{
110+
var q = await client.GetAsync(url);
111+
Assert.That(q.IsSuccessStatusCode);
112+
}
113+
Console.WriteLine($"fuck httpclient");
124114

125-
var h2 = new HttpClientHandler()
126-
{
127-
AllowAutoRedirect = true,
128-
Proxy = new WebProxy("http://127.0.0.1:8888"),
129-
UseProxy = true
130-
};
131-
using (var client = new HttpClient(h2))
132-
{
133-
client.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
134-
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
135-
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5");
115+
{
116+
client = new HttpClient();
136117

137-
var q = await client.GetAsync(url, cts.Token); //third request r3 //failed
138-
Assert.That(q.IsSuccessStatusCode);
139-
}
118+
var q = await client.GetAsync(url);
119+
Assert.That(q.IsSuccessStatusCode);
140120
}
141121
}
142122
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using NUnit.Framework;
2+
using WeChatBot.Net.Extensions;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Net;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using Flurl.Http;
10+
11+
namespace WeChatBot.Net.Extensions.Tests
12+
{
13+
[TestFixture()]
14+
public class FlurlClientExtensionsTests
15+
{
16+
/// <summary>
17+
/// Exception: This instance has already started one or more requests. Properties can only be modified before sending the first request.
18+
/// </summary>
19+
/// <returns></returns>
20+
[Test()]
21+
public async Task WithNewHttpClientTest()
22+
{
23+
var url = @"https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=1&uuid=YenIkE0Lsw==&_=1474877000";
24+
var flurlClient = new FlurlClient() { AutoDispose = false };
25+
26+
{
27+
var q = await url.WithClient(flurlClient).WithTimeout(TimeSpan.FromSeconds(5)).GetAsync();
28+
Assert.That(q.IsSuccessStatusCode);
29+
await q.Content.ReadAsStringAsync();
30+
}
31+
Assert.ThrowsAsync<InvalidOperationException>(async () =>
32+
{
33+
{
34+
var q = await url.WithClient(flurlClient).WithTimeout(TimeSpan.FromSeconds(5)).GetAsync();
35+
Assert.That(q.IsSuccessStatusCode);
36+
}
37+
});
38+
}
39+
40+
/// <summary>
41+
///
42+
/// </summary>
43+
/// <returns></returns>
44+
[Test()]
45+
public async Task WithNewHttpClientTest2()
46+
{
47+
var url = @"https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=1&uuid=YenIkE0Lsw==&_=1474877000";
48+
var flurlClient = new FlurlClient() { AutoDispose = false };
49+
50+
{
51+
var q = await url.WithClient(flurlClient).WithTimeout(TimeSpan.FromSeconds(5)).GetAsync();
52+
Assert.That(q.IsSuccessStatusCode);
53+
await q.Content.ReadAsStringAsync();
54+
}
55+
Console.WriteLine($"fuck httpclient");
56+
{
57+
58+
59+
var q = await url.WithClient(flurlClient).WithNewHttpClient().GetAsync();
60+
61+
//var q2 = await url.WithClient(flurlClient).WithNewHttpClient().WithTimeout(TimeSpan.FromSeconds(5)).GetAsync();
62+
Assert.That(q.IsSuccessStatusCode);
63+
}
64+
}
65+
}
66+
}

WeChatBot.Net.Tests/WeChatBot.Net.Tests.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
</ItemGroup>
6868
<ItemGroup>
6969
<Compile Include="ClientTests.cs" />
70+
<Compile Include="Extensions\FlurlClientExtensionsTests.cs" />
7071
<Compile Include="Properties\AssemblyInfo.cs" />
7172
<Compile Include="Util\ImageExtensionsTests.cs" />
7273
</ItemGroup>
@@ -77,6 +78,7 @@
7778
</ProjectReference>
7879
</ItemGroup>
7980
<ItemGroup>
81+
<None Include="App.config" />
8082
<None Include="packages.config" />
8183
</ItemGroup>
8284
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

WeChatBot.Net/Extensions/FlurlClientExtensions.cs

+22
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,34 @@
44
using System.Threading.Tasks;
55
using Flurl;
66
using Flurl.Http;
7+
using Flurl.Http.Configuration;
78
using WeChatBot.Net.Helper;
89

910
namespace WeChatBot.Net.Extensions
1011
{
1112
public static class FlurlClientExtensions
1213
{
14+
/// <summary>
15+
/// </summary>
16+
/// <param name="flurlClient"></param>
17+
public static FlurlClient WithNewHttpClient(this FlurlClient flurlClient)
18+
{
19+
var client = new FlurlClient()
20+
{
21+
AutoDispose = true
22+
}
23+
.EnableCookies()
24+
.ConfigureClient(x =>
25+
{
26+
x.HttpClientFactory = new CustomHttpClientFactory();
27+
})
28+
.WithUrl(flurlClient.Url)
29+
.WithCookies(flurlClient.Cookies)
30+
.WithHeaders(flurlClient.HttpClient.DefaultRequestHeaders)
31+
;
32+
return client;
33+
}
34+
1335
/// <summary>
1436
/// Fluently specify that an existing FlurlClient should be used to call the Url, rather than creating a new one.
1537
/// Enables re-using the underlying HttpClient.

0 commit comments

Comments
 (0)