示例#1
0
        private static HttpResponse ManualPost(this HttpRequest request, Uri uri, string postData, string contentType, Uri refererUri = null, RequestParams requestParams = null)
        {
            request.ManualMode = true;
            // Manual start

            request.AddCloudflareHeaders(refererUri ?? uri);
            HttpResponse response;

            if (string.IsNullOrEmpty(postData) & contentType != "application/x-www-form-urlencoded")
            {
                var stringContent = new StringContent(string.Empty)
                {
                    ContentType = contentType
                };
                response = request.Raw(HttpMethod.POST, uri, stringContent);
            }
            else if (!string.IsNullOrEmpty(postData))
            {
                response = request.Post(uri, postData, contentType);
            }
            else
            {
                response = request.Post(uri);
            }

            // End manual mode
            request.ManualMode = false;

            return(response);
        }
示例#2
0
        private static HttpResponse ManualGet(HttpRequest request, string url, string refererUrl = null)
        {
            request.ManualMode = true;

            request.AddCloudflareHeaders(refererUrl ?? url);
            var response = request.Get(url);

            request.ManualMode = false;

            return(response);
        }
示例#3
0
        private static HttpResponse ManualGet(this HttpRequest request, Uri uri, Uri refererUri = null, RequestParams requestParams = null)
        {
            request.ManualMode = true;
            // Manual start

            request.AddCloudflareHeaders(refererUri ?? uri);
            var response = requestParams == null?request.Get(uri) : request.Get(uri, requestParams);

            // End manual mode
            request.ManualMode = false;

            return(response);
        }
示例#4
0
        private static bool IsChallengePassed(string tag, ref HttpResponse response, HttpRequest request, Uri uri, string retry, DLog log)
        {
            // ReSharper disable once SwitchStatementMissingSomeCases
            switch (response.StatusCode)
            {
            case HttpStatusCode.ServiceUnavailable:
            case HttpStatusCode.Forbidden:
                return(false);

            case HttpStatusCode.Found:
                // Т.к. ранее использовался ручной режим - нужно обработать редирект, если он есть, чтобы вернуть отфильтрованное тело запроса
                if (response.HasRedirect)
                {
                    if (!response.ContainsCookie(uri, CfClearanceCookie))
                    {
                        return(false);
                    }

                    log?.Invoke($"{LogPrefix}Passed [{tag}]. Trying to get the original response at: {uri.AbsoluteUri} ...");

                    // Не используем manual т.к. могут быть переадресации
                    bool ignoreProtocolErrors = request.IgnoreProtocolErrors;
                    // Отключаем обработку HTTP ошибок
                    request.IgnoreProtocolErrors = true;

                    request.AddCloudflareHeaders(uri);     // заголовки важны для прохождения cloudflare
                    response = request.Get(response.RedirectAddress.AbsoluteUri);
                    request.IgnoreProtocolErrors = ignoreProtocolErrors;

#pragma warning disable 618
                    if (IsCloudflared(response))
#pragma warning restore 618
                    {
                        log?.Invoke($"{LogPrefix}ERROR [{tag}]. Unable to get he original response at: {uri.AbsoluteUri}");
                        return(false);
                    }
                }

                log?.Invoke($"{LogPrefix}OK [{tag}]. Done: {uri.AbsoluteUri}");
                return(true);
            }

            log?.Invoke($"{LogPrefix}ERROR [{tag}]. Status code : {response.StatusCode}{retry}.");
            return(false);
        }
示例#5
0
        /// <summary>
        /// GET request with bypassing Cloudflare JavaScript challenge.
        /// </summary>
        /// <param name="request">Http request</param>
        /// <param name="url">Address</param>
        /// <param name="log">Log action</param>
        /// <param name="cancellationToken">Cancel protection</param>
        /// <returns>Returns original HttpResponse</returns>
        public static HttpResponse GetThroughCloudflare(this HttpRequest request, string url,
                                                        DLog log = null,
                                                        CancellationToken cancellationToken = default(CancellationToken))
        {
            if (request.DontTrackCookies)
            {
                throw new HttpException("В свойствах HTTP запроса отключена обработка Cookies через свойство DontTrackCookies. Для CloudFlare куки обязательны.");
            }

            // User-Agent is required
            if (string.IsNullOrEmpty(request.UserAgent))
            {
                request.UserAgent = Http.ChromeUserAgent();
            }

            log?.Invoke("Проверяем наличие CloudFlare по адресу: " + url);

            for (int i = 0; i < MaxRetries; i++)
            {
                string retry = $". Попытка {i + 1} из {MaxRetries}.";
                log?.Invoke("Обхожу CloudFlare" + retry);


                var response = ManualGet(request, url);
                if (!response.IsCloudflared())
                {
                    log?.Invoke("УСПЕХ: Cloudflare не обнаружен, работаем дальше: " + url);
                    return(response);
                }

                // Remove expired clearance if present
                var cookies = request.Cookies.GetCookies(url);
                foreach (Cookie cookie in cookies)
                {
                    if (cookie.Name != CfClearanceCookie)
                    {
                        continue;
                    }

                    cookie.Expired = true;
                    break;
                }

                if (cancellationToken != default(CancellationToken))
                {
                    cancellationToken.ThrowIfCancellationRequested();
                }

                response = PassClearance(request, response, url, log, cancellationToken);

                // ReSharper disable once SwitchStatementMissingSomeCases
                switch (response.StatusCode)
                {
                case HttpStatusCode.ServiceUnavailable:
                case HttpStatusCode.Forbidden:
                    continue;

                case HttpStatusCode.Found:
                    // Т.к. ранее использовался ручной режим - нужно обработать редирект, если он есть, чтобы вернуть отфильтрованное тело запроса
                    if (response.HasRedirect)
                    {
                        if (!response.ContainsCookie(url, CfClearanceCookie))
                        {
                            continue;
                        }

                        log?.Invoke($"CloudFlare этап пройден, получаю оригинальную страницу: {url}...");

                        // Не используем manual т.к. могут быть переадресации
                        bool ignoreProtocolErrors = request.IgnoreProtocolErrors;
                        // Отключаем обработку HTTP ошибок
                        request.IgnoreProtocolErrors = true;

                        request.AddCloudflareHeaders(url);     // заголовки важны для прохождения cloudflare
                        response = request.Get(response.RedirectAddress.AbsoluteUri);
                        request.IgnoreProtocolErrors = ignoreProtocolErrors;

                        if (IsCloudflared(response))
                        {
                            log?.Invoke($"Ошибка CloudFlare: этап пройден, но оригинальная страница не получена: {url}");
                            continue;
                        }
                    }

                    log?.Invoke($"CloudFlare: успех, оригинальная страница получена: {url}");
                    return(response);
                }

                log?.Invoke($"CloudFlare не смог пройти JS Challenge, причина не ясна. Статус код: {response.StatusCode}" + retry);
            }

            throw new CloudflareException(MaxRetries, "Превышен лимит попыток обхода Cloudflare");
        }