2
2
using System . Net ;
3
3
using System . Net . Http ;
4
4
using System . Runtime . CompilerServices ;
5
+ using System . Threading ;
6
+ using System . Threading . Tasks ;
5
7
6
8
namespace DotnetSpider . Core . Downloader
7
9
{
@@ -14,20 +16,6 @@ public class HttpClientEntry
14
16
15
17
internal HttpClientHandler Handler { get ; private set ; }
16
18
17
- public HttpClientEntry ( )
18
- {
19
- Handler = new HttpClientHandler
20
- {
21
- AutomaticDecompression = DecompressionMethods . Deflate | DecompressionMethods . GZip ,
22
- UseProxy = true ,
23
- UseCookies = true ,
24
- AllowAutoRedirect = true ,
25
- MaxAutomaticRedirections = 10
26
- } ;
27
- Client = new HttpClient ( Handler ) ;
28
- ActiveTime = DateTime . Now ;
29
- }
30
-
31
19
internal CookieContainer CookieContainer
32
20
{
33
21
set
@@ -40,17 +28,104 @@ internal CookieContainer CookieContainer
40
28
}
41
29
42
30
[ MethodImpl ( MethodImplOptions . Synchronized ) ]
43
- internal void Init ( Action configAction , Func < CookieContainer > cookieContainerFactory )
31
+ internal void Init ( bool allowAutoRedirect , Action configAction , Func < CookieContainer > cookieContainerFactory )
44
32
{
45
33
if ( _inited )
46
34
{
47
35
return ;
48
36
}
49
37
38
+ Handler = new HttpClientHandler
39
+ {
40
+ AutomaticDecompression = DecompressionMethods . Deflate | DecompressionMethods . GZip ,
41
+ UseProxy = true ,
42
+ UseCookies = true ,
43
+ AllowAutoRedirect = true ,
44
+ MaxAutomaticRedirections = 10
45
+ } ;
46
+ Client = allowAutoRedirect ? new HttpClient ( new GlobalRedirectHandler ( Handler ) ) : new HttpClient ( Handler ) ;
47
+ ActiveTime = DateTime . Now ;
48
+
50
49
configAction ( ) ;
50
+
51
51
Handler . CookieContainer = cookieContainerFactory ( ) ;
52
+
52
53
_inited = true ;
53
54
}
55
+
56
+ public class GlobalRedirectHandler : DelegatingHandler
57
+ {
58
+ public GlobalRedirectHandler ( HttpMessageHandler innerHandler )
59
+ {
60
+ InnerHandler = innerHandler ;
61
+ }
62
+
63
+ protected override Task < HttpResponseMessage > SendAsync ( HttpRequestMessage request , CancellationToken cancellationToken )
64
+ {
65
+ var tcs = new TaskCompletionSource < HttpResponseMessage > ( ) ;
66
+
67
+ base . SendAsync ( request , cancellationToken )
68
+ . ContinueWith ( t =>
69
+ {
70
+ HttpResponseMessage response ;
71
+ try
72
+ {
73
+ response = t . Result ;
74
+ }
75
+ catch ( Exception e )
76
+ {
77
+ response = new HttpResponseMessage ( HttpStatusCode . ServiceUnavailable ) { ReasonPhrase = e . Message } ;
78
+ }
79
+ if ( response . StatusCode == HttpStatusCode . MovedPermanently
80
+ || response . StatusCode == HttpStatusCode . Moved
81
+ || response . StatusCode == HttpStatusCode . Redirect
82
+ || response . StatusCode == HttpStatusCode . Found
83
+ || response . StatusCode == HttpStatusCode . SeeOther
84
+ || response . StatusCode == HttpStatusCode . RedirectKeepVerb
85
+ || response . StatusCode == HttpStatusCode . TemporaryRedirect
86
+ || ( int ) response . StatusCode == 308 )
87
+ {
88
+
89
+ var newRequest = CopyRequest ( response . RequestMessage ) ;
90
+
91
+ if ( response . StatusCode == HttpStatusCode . Redirect
92
+ || response . StatusCode == HttpStatusCode . Found
93
+ || response . StatusCode == HttpStatusCode . SeeOther )
94
+ {
95
+ newRequest . Content = null ;
96
+ newRequest . Method = HttpMethod . Get ;
97
+
98
+ }
99
+ newRequest . RequestUri = response . Headers . Location ;
100
+
101
+ base . SendAsync ( newRequest , cancellationToken )
102
+ . ContinueWith ( t2 => tcs . SetResult ( t2 . Result ) , cancellationToken ) ;
103
+ }
104
+ else
105
+ {
106
+ tcs . SetResult ( response ) ;
107
+ }
108
+ } , cancellationToken ) ;
109
+
110
+ return tcs . Task ;
111
+ }
112
+
113
+ private static HttpRequestMessage CopyRequest ( HttpRequestMessage oldRequest )
114
+ {
115
+ var newrequest = new HttpRequestMessage ( oldRequest . Method , oldRequest . RequestUri ) ;
116
+
117
+ foreach ( var header in oldRequest . Headers )
118
+ {
119
+ newrequest . Headers . TryAddWithoutValidation ( header . Key , header . Value ) ;
120
+ }
121
+ foreach ( var property in oldRequest . Properties )
122
+ {
123
+ newrequest . Properties . Add ( property ) ;
124
+ }
125
+ if ( oldRequest . Content != null ) newrequest . Content = new StreamContent ( oldRequest . Content . ReadAsStreamAsync ( ) . Result ) ;
126
+ return newrequest ;
127
+ }
128
+ }
54
129
}
55
130
56
131
/// <summary>
0 commit comments