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); }
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); }
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); }
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); }
/// <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"); }