AngleSharp by AngleSharp

<PackageReference Include="AngleSharp" Version="0.9.7" />

.NET API 1,204,224 bytes

 RequesterExtensions

static class RequesterExtensions
Useful extensions for IRequester objects.
using AngleSharp.Dom; using AngleSharp.Network; using System; using System.Diagnostics; using System.Net; using System.Threading; using System.Threading.Tasks; namespace AngleSharp.Extensions { [DebuggerStepThrough] internal static class RequesterExtensions { public static IDownload FetchWithCors(this IResourceLoader loader, ResourceRequest request, CorsSetting setting, OriginBehavior behavior) { Url target = request.Target; if (!(request.Origin == target.Origin) && !(target.Scheme == ProtocolNames.Data) && !(target.Href == "about:blank")) { switch (setting) { case CorsSetting.Anonymous: case CorsSetting.UseCredentials: return loader.FetchWithCors(request, setting); case CorsSetting.None: return loader.FetchWithoutCors(request, behavior); default: throw new DomException(DomError.Network); } } return loader.FetchWithCors(target, request, setting, behavior); } private static IDownload FetchWithCors(this IResourceLoader loader, Url url, ResourceRequest request, CorsSetting setting, OriginBehavior behavior) { IDownload download = loader.DownloadAsync(new ResourceRequest(request.Source, url) { Origin = request.Origin, IsManualRedirectDesired = true }); return download.Wrap(delegate(IResponse response) { if (response.IsRedirected()) { url.Href = response.Headers.GetOrDefault(HeaderNames.Location, url.Href); if (request.Origin.Is(url.Origin)) return loader.FetchWithCors(new ResourceRequest(request.Source, url) { IsCookieBlocked = request.IsCookieBlocked, IsSameOriginForced = request.IsSameOriginForced, Origin = request.Origin }, setting, behavior); return loader.FetchWithCors(url, request, setting, behavior); } return download; }); } private static IDownload FetchWithoutCors(this IResourceLoader loader, ResourceRequest request, OriginBehavior behavior) { if (behavior == OriginBehavior.Fail) throw new DomException(DomError.Network); return loader.DownloadAsync(request); } private static IDownload FetchWithCors(this IResourceLoader loader, ResourceRequest request, CorsSetting setting) { request.IsCredentialOmitted = (setting == CorsSetting.Anonymous); IDownload download = loader.DownloadAsync(request); return download.Wrap(delegate(IResponse response) { if (response != null && response.StatusCode == HttpStatusCode.OK) return download; response?.Dispose(); throw new DomException(DomError.Network); }); } private static IDownload Wrap(this IDownload download, Func<IResponse, IDownload> callback) { CancellationTokenSource cts = new CancellationTokenSource(); return new Download(download.Task.Wrap(callback), cts, download.Target, download.Originator); } private static async Task<IResponse> Wrap(this Task<IResponse> task, Func<IResponse, IDownload> callback) { return await callback(await task.ConfigureAwait(false)).Task.ConfigureAwait(false); } private static bool IsRedirected(this IResponse response) { HttpStatusCode httpStatusCode = response?.StatusCode ?? HttpStatusCode.NotFound; switch (httpStatusCode) { default: return httpStatusCode == HttpStatusCode.MultipleChoices; case HttpStatusCode.MovedPermanently: case HttpStatusCode.Found: case HttpStatusCode.SeeOther: case HttpStatusCode.TemporaryRedirect: return true; } } } }