22using System . Net ;
33using System . Net . Http ;
44using System . Runtime . CompilerServices ;
5+ using System . Threading ;
6+ using System . Threading . Tasks ;
57
68namespace DotnetSpider . Core . Downloader
79{
@@ -14,20 +16,6 @@ public class HttpClientEntry
1416
1517 internal HttpClientHandler Handler { get ; private set ; }
1618
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-
3119 internal CookieContainer CookieContainer
3220 {
3321 set
@@ -40,17 +28,104 @@ internal CookieContainer CookieContainer
4028 }
4129
4230 [ MethodImpl ( MethodImplOptions . Synchronized ) ]
43- internal void Init ( Action configAction , Func < CookieContainer > cookieContainerFactory )
31+ internal void Init ( bool allowAutoRedirect , Action configAction , Func < CookieContainer > cookieContainerFactory )
4432 {
4533 if ( _inited )
4634 {
4735 return ;
4836 }
4937
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+
5049 configAction ( ) ;
50+
5151 Handler . CookieContainer = cookieContainerFactory ( ) ;
52+
5253 _inited = true ;
5354 }
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+ }
54129 }
55130
56131 /// <summary>
0 commit comments