public async Task <Response> DownloadAsync(Request request)
        {
            Response            response            = null;
            HttpClientEntry     httpClientEntry     = null;
            HttpResponseMessage httpResponseMessage = null;

            try
            {
                var httpRequest = request.ToHttpRequestMessage();
                httpClientEntry = await CreateAsync(request);

                var stopwatch = new Stopwatch();
                stopwatch.Start();

                httpResponseMessage = await httpClientEntry.HttpClient.SendAsync(httpRequest);

                stopwatch.Stop();

                response = await HandleAsync(request, httpResponseMessage);

                if (response != null)
                {
                    return(response);
                }

                response = await httpResponseMessage.ToResponseAsync();

                response.ElapsedMilliseconds = (int)stopwatch.ElapsedMilliseconds;
                response.RequestHash         = request.Hash;

                return(response);
            }
            catch (Exception e)
            {
                Logger.LogError($"{request.RequestUri} download failed: {e}");
                response = new Response
                {
                    RequestHash = request.Hash, StatusCode = HttpStatusCode.Gone, ReasonPhrase = e.ToString()
                };
                return(response);
            }
            finally
            {
                DisposeSafely(httpResponseMessage);

                Release(response, httpClientEntry);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Return same <see cref="HttpClientEntry"/> instance when <paramref name="hash"/> is same.
        /// This can ensure some pages have same CookieContainer.
        /// </summary>
        /// <summary xml:lang="zh-CN">
        /// 通过不同的Hash分组, 返回对应的HttpClient
        /// 设计初衷: 某些网站会对COOKIE某部分做承上启下的检测, 因此必须保证: www.a.com/keyword=xxxx&amp;page=1 www.a.com/keyword=xxxx&amp;page=2 在同一个HttpClient里访问
        /// </summary>
        /// <param name="hash">分组的哈希 Hashcode to identify different group.</param>
        /// <param name="proxy">代理</param>
        /// <returns>HttpClientItem</returns>
        private HttpClientEntry GetHttpClientEntry(string hash, IWebProxy proxy)
        {
            if (string.IsNullOrWhiteSpace(hash))
            {
                hash = string.Empty;
            }

            Interlocked.Increment(ref _getHttpClientCount);

            if (_getHttpClientCount % 100 == 0)
            {
                CleanupPool();
            }

            if (_httpClients.ContainsKey(hash))
            {
                _httpClients[hash].LastUseTime = DateTime.Now;
                return(_httpClients[hash]);
            }
            else
            {
                var handler = new HttpClientHandler
                {
                    AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
                    UseProxy          = UseProxy,
                    UseCookies        = UseCookies,
                    AllowAutoRedirect = false,
                    Proxy             = proxy,
                    CookieContainer   = _cookieContainer
                };
                var item = new HttpClientEntry(handler, AllowAutoRedirect)
                {
                    LastUseTime = DateTime.Now
                };
                item.HttpClient.Timeout = new TimeSpan(0, 0, 0, Timeout);
                _httpClients.TryAdd(hash, item);
                return(item);
            }
        }
Esempio n. 3
0
 protected override void Release(Response response, HttpClientEntry httpClientEntry)
 {
     _proxyService.ReturnAsync(httpClientEntry.Resource,
                               response?.StatusCode ?? HttpStatusCode.NotFound);
 }
 protected virtual void Release(Response response, HttpClientEntry httpClientEntry)
 {
 }
Esempio n. 5
0
        public async Task <Response> DownloadAsync(Request request)
        {
            Response        response        = null;
            HttpClientEntry httpClientEntry = null;

            try
            {
                var httpRequest = GenerateHttpRequestMessage(request);
                httpClientEntry = await CreateAsync(request);

                var stopwatch = new Stopwatch();
                stopwatch.Start();
                var httpResponseMessage = await httpClientEntry.HttpClient.SendAsync(httpRequest);

                stopwatch.Stop();

                response = await HandleAsync(request, httpResponseMessage);

                if (response != null)
                {
                    return(response);
                }

                response = new Response
                {
                    ElapsedMilliseconds = (int)stopwatch.ElapsedMilliseconds,
                    StatusCode          = httpResponseMessage.StatusCode
                };
                foreach (var header in httpResponseMessage.Headers)
                {
                    response.Headers.Add(header.Key, new HashSet <string>(header.Value));
                }

                response.RequestHash = request.Hash;
                response.Content     = new ResponseContent
                {
                    Data = await httpResponseMessage.Content.ReadAsByteArrayAsync()
                };
                foreach (var header in httpResponseMessage.Content.Headers)
                {
                    response.Content.Headers.Add(header.Key, new HashSet <string>(header.Value));
                }

                return(response);
            }
            catch (Exception e)
            {
                Logger.LogError($"{request.Url} download failed: {e}");
                response = new Response
                {
                    RequestHash = request.Hash,
                    StatusCode  = HttpStatusCode.BadGateway,
                    Content     = new ResponseContent {
                        Data = Encoding.UTF8.GetBytes(e.ToString())
                    }
                };
                return(response);
            }
            finally
            {
                Release(response, httpClientEntry);
            }
        }