diff --git a/.editorconfig b/.editorconfig index 0c21054..e50f5b5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -26,3 +26,6 @@ dotnet_diagnostic.IDE0047.severity = none # DV2001: No Dependency Diagram linked dotnet_diagnostic.DV2001.severity = none + +# CS8602: Dereference of a possibly null reference. +dotnet_diagnostic.CS8602.severity = silent diff --git a/UniversalExtensions.cs b/UniversalExtensions.cs index 3942fda..409f827 100644 --- a/UniversalExtensions.cs +++ b/UniversalExtensions.cs @@ -104,20 +104,60 @@ public static class UniversalExtensions /// /// The shortened URL /// The URL the redirect leads to - public static async Task UnshortenUrl(string url) + public static async Task UnshortenUrl(string url, bool UseHeadMethod = true) { - HttpClient client = new(new HttpClientHandler() { AllowAutoRedirect = false }); - var request = await client.GetAsync(url); + HttpClient client = new(new HttpClientHandler() + { + AllowAutoRedirect = false, + AutomaticDecompression = DecompressionMethods.GZip, + + }); + client.Timeout = TimeSpan.FromSeconds(10); + client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"); + client.DefaultRequestHeaders.Add("upgrade-insecure-requests", "1"); + client.DefaultRequestHeaders.Add("accept-encoding", "gzip, deflate, br"); + client.DefaultRequestHeaders.Add("accept-language", "en-US,en;q=0.9"); + client.MaxResponseContentBufferSize = 4096; - if (request.StatusCode is HttpStatusCode.Found + HttpRequestMessage requestMessage = new HttpRequestMessage((UseHeadMethod ? HttpMethod.Head : HttpMethod.Get), url); + + CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + var request_task = client.SendAsync(requestMessage, cancellationTokenSource.Token); + + try + { + await request_task.WaitAsync(TimeSpan.FromSeconds(3)); + } + catch (Exception) + { + if (UseHeadMethod) + return await UnshortenUrl(url, false); + + throw; + } + + if (!request_task.IsCompleted) + cancellationTokenSource.Cancel(); + + if (UseHeadMethod && request_task.IsFaulted && request_task.Exception.InnerException.GetType().FullName == "System.Net.Http.HttpRequestException") + return await UnshortenUrl(url, false); + + var statuscode = request_task.Result.StatusCode; + var header = request_task.Result.Headers; + + if (UseHeadMethod && statuscode is HttpStatusCode.NotFound or HttpStatusCode.InternalServerError) + return await UnshortenUrl(url, false); + + if (statuscode is HttpStatusCode.Found or HttpStatusCode.Redirect + or HttpStatusCode.SeeOther or HttpStatusCode.RedirectKeepVerb or HttpStatusCode.RedirectMethod or HttpStatusCode.PermanentRedirect or HttpStatusCode.TemporaryRedirect) { - if (request.Headers is not null && request.Headers.Location is not null) - return await UnshortenUrl(request.Headers.Location.AbsoluteUri); + if (header is not null && header.Location is not null) + return await UnshortenUrl(header.Location.AbsoluteUri); else return url; }