AngleSharp by AngleSharp

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

.NET API 1,230,336 bytes

 RequesterExtensions

static class RequesterExtensions
Useful extensions for IRequester objects.
using AngleSharp.Dom; using AngleSharp.Html; using AngleSharp.Network; using AngleSharp.Network.Default; using AngleSharp.Services; using System; using System.IO; using System.Net; using System.Threading; using System.Threading.Tasks; namespace AngleSharp.Extensions { internal static class RequesterExtensions { public static bool IsRedirected(this HttpStatusCode status) { switch (status) { default: return status == HttpStatusCode.MultipleChoices; case HttpStatusCode.MovedPermanently: case HttpStatusCode.Found: case HttpStatusCode.SeeOther: case HttpStatusCode.TemporaryRedirect: return true; } } public static IDownload FetchWithCors(this IResourceLoader loader, CorsRequest cors) { ResourceRequest request = cors.Request; CorsSetting setting = cors.Setting; 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.FetchFromDifferentOrigin(cors); case CorsSetting.None: return loader.FetchWithoutCors(request, cors.Behavior); default: throw new DomException(DomError.Network); } } return loader.FetchFromSameOrigin(target, cors); } private static IDownload FetchFromSameOrigin(this IResourceLoader loader, Url url, CorsRequest cors) { ResourceRequest request = cors.Request; 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.FetchFromSameOrigin(url, cors); return loader.FetchWithCors(cors.RedirectTo(url)); } return cors.CheckIntegrity(download); }); } private static IDownload FetchFromDifferentOrigin(this IResourceLoader loader, CorsRequest cors) { ResourceRequest request = cors.Request; request.IsCredentialOmitted = cors.IsAnonymous(); IDownload download = loader.DownloadAsync(request); return download.Wrap(delegate(IResponse response) { if (response == null || response.StatusCode != HttpStatusCode.OK) { response?.Dispose(); throw new DomException(DomError.Network); } return cors.CheckIntegrity(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 bool IsAnonymous(this CorsRequest cors) { return cors.Setting == CorsSetting.Anonymous; } 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 IDownload Wrap(this IDownload download, IResponse response) { CancellationTokenSource cts = new CancellationTokenSource(); return new Download(TaskEx.FromResult(response), 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) { return (response?.StatusCode ?? HttpStatusCode.NotFound).IsRedirected(); } private static CorsRequest RedirectTo(this CorsRequest cors, Url url) { ResourceRequest request = cors.Request; return new CorsRequest(new ResourceRequest(request.Source, url) { IsCookieBlocked = request.IsCookieBlocked, IsSameOriginForced = request.IsSameOriginForced, Origin = request.Origin }) { Setting = cors.Setting, Behavior = cors.Behavior, Integrity = cors.Integrity }; } private static IDownload CheckIntegrity(this CorsRequest cors, IDownload download) { IResponse result = download.Task.Result; string text = cors.Request.Source?.GetAttribute(AttributeNames.Integrity); IIntegrityProvider integrity = cors.Integrity; if (!string.IsNullOrEmpty(text) && integrity != null && result != null) { MemoryStream memoryStream = new MemoryStream(); result.Content.CopyTo(memoryStream); memoryStream.Position = 0; if (!integrity.IsSatisfied(memoryStream.ToArray(), text)) { result.Dispose(); throw new DomException(DomError.Security); } return download.Wrap(new Response { Address = result.Address, Content = memoryStream, Headers = result.Headers, StatusCode = result.StatusCode }); } return download; } } }