From af488e4e56091c08951ed5cbbe168f10dd2b953c Mon Sep 17 00:00:00 2001 From: Ferlorin Date: Tue, 12 Nov 2024 03:05:04 +0200 Subject: [PATCH 1/3] Token in GET parameters in case Headers authentication is down --- Gw2Sharp/WebApi/V2/RequestBuilder.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Gw2Sharp/WebApi/V2/RequestBuilder.cs b/Gw2Sharp/WebApi/V2/RequestBuilder.cs index f595f6818..f388d4ebb 100644 --- a/Gw2Sharp/WebApi/V2/RequestBuilder.cs +++ b/Gw2Sharp/WebApi/V2/RequestBuilder.cs @@ -39,6 +39,7 @@ internal class RequestBuilder private readonly IConnection connection; private readonly IGw2Client gw2Client; private readonly string? authorization; + private readonly string? token; private readonly string? locale; private readonly string userAgent; @@ -59,7 +60,8 @@ public RequestBuilder(IEndpointClient endpointClient, IConnection connection, IG this.connection = connection; this.gw2Client = gw2Client; - this.authorization = endpointClient.IsAuthenticated ? $"{BEARER} {connection.AccessToken}" : null; + this.token = endpointClient.IsAuthenticated ? connection.AccessToken : null; + this.authorization = endpointClient.IsAuthenticated ? $"{BEARER} {this.token}" : null; this.locale = endpointClient.IsLocalized ? connection.LocaleString : null; this.userAgent = connection.UserAgent; } @@ -133,12 +135,14 @@ public IWebApiRequest Page(int page, int pageSize = MAX_PAGE_SIZE) private IDictionary? BuildQueryParams(IDictionary? additionalQueryParams = null) { - if (this.queryParams.Count == 0) - return additionalQueryParams; var combinedQueryParams = new Dictionary(this.queryParams); + + if (!string.IsNullOrWhiteSpace(this.token)) + combinedQueryParams["access_token"] = this.token; + if (additionalQueryParams != null) combinedQueryParams.AddRange(additionalQueryParams); - return combinedQueryParams; + return (combinedQueryParams.Count == 0) ? additionalQueryParams : combinedQueryParams; } private IDictionary BuildHeaders() From 0f43ad77b4b5f817e8fbcbc6b6021d075187b26e Mon Sep 17 00:00:00 2001 From: Ferlorin Date: Tue, 12 Nov 2024 14:32:33 +0200 Subject: [PATCH 2/3] since we added the parameter the tests were not asserting the urls are equal --- .../WebApi/V2/Clients/BaseEndpointClientTests.cs | 2 +- Gw2Sharp/WebApi/Http/WebApiRequestOptions.cs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Gw2Sharp.Tests/WebApi/V2/Clients/BaseEndpointClientTests.cs b/Gw2Sharp.Tests/WebApi/V2/Clients/BaseEndpointClientTests.cs index edef1e182..08141e725 100644 --- a/Gw2Sharp.Tests/WebApi/V2/Clients/BaseEndpointClientTests.cs +++ b/Gw2Sharp.Tests/WebApi/V2/Clients/BaseEndpointClientTests.cs @@ -227,7 +227,7 @@ protected virtual void AssertRequest(CallInfo callInfo, IEndpointClient client, uri = builder.Uri; } - Assert.Equal(uri.AbsoluteUri, callInfo.ArgAt(0).Options.Url.AbsoluteUri); + Assert.Equal(uri.AbsoluteUri, callInfo.ArgAt(0).Options.UrlWithoutAuth.AbsoluteUri); var requestHeaders = callInfo.ArgAt(0).Options.RequestHeaders; Assert.Contains(new KeyValuePair("Accept", "application/json"), requestHeaders); Assert.Contains(new KeyValuePair("User-Agent", ((Gw2WebApiBaseClient)client).Connection.UserAgent), requestHeaders); diff --git a/Gw2Sharp/WebApi/Http/WebApiRequestOptions.cs b/Gw2Sharp/WebApi/Http/WebApiRequestOptions.cs index 0b311290a..70c010adb 100644 --- a/Gw2Sharp/WebApi/Http/WebApiRequestOptions.cs +++ b/Gw2Sharp/WebApi/Http/WebApiRequestOptions.cs @@ -64,6 +64,22 @@ public Uri Url } } + /// + /// The URL without the authentication parameter. + /// + public Uri UrlWithoutAuth + { + get + { + var builder = new UriBuilder(this.BaseUrl); + builder.Path += this.EndpointPath; + if (!string.IsNullOrEmpty(this.PathSuffix)) + builder.Path += !this.PathSuffix.StartsWith("/", StringComparison.InvariantCulture) ? "/" : string.Empty + this.PathSuffix; + builder.Query = string.Join("&", this.EndpointQuery.Where(x => x.Key != "access_token").Select(x => $"{Uri.EscapeDataString(x.Key)}{(x.Value != null ? $"={Uri.EscapeDataString(x.Value)}" : "")}")); + return builder.Uri; + } + } + #pragma warning disable CA2227 // Collection properties should be read only /// /// The request headers to use in the web request. From 2ad103fb5f505ec35d8b935e013b4ca0b91569ea Mon Sep 17 00:00:00 2001 From: Ferlorin Date: Tue, 12 Nov 2024 17:22:26 +0200 Subject: [PATCH 3/3] remove header authentication if NotFound, so that it works --- Gw2Sharp/WebApi/Http/HttpClient.cs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Gw2Sharp/WebApi/Http/HttpClient.cs b/Gw2Sharp/WebApi/Http/HttpClient.cs index 3b8444764..de34793cd 100644 --- a/Gw2Sharp/WebApi/Http/HttpClient.cs +++ b/Gw2Sharp/WebApi/Http/HttpClient.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using System.Net; using System.Threading; using System.Threading.Tasks; using Gw2Sharp.Extensions; @@ -67,7 +68,7 @@ public Task RequestStreamAsync(IWebApiRequest request, Canc async Task ExecAsync() { - using var message = new HttpRequestMessage(HttpMethod.Get, request.Options.Url); + using var message = new HttpRequestMessage(HttpMethod.Get, request.Options.UrlWithoutAuth); message.Headers.AddRange(request.Options.RequestHeaders); Task? task = null; @@ -84,6 +85,24 @@ async Task ExecAsync() task = httpClient.SendAsync(message, cancellationToken); var responseMessage = await task.ConfigureAwait(false); + if (responseMessage.StatusCode == HttpStatusCode.NotFound && + message.Headers.Contains("Authorization") && + message.Headers.GetValues("Authorization").First() != "Bearer") + { + using var newMessage = new HttpRequestMessage(HttpMethod.Get, request.Options.Url); + foreach (var header in message.Headers) + { + if (header.Key == "Authorization") + continue; + + newMessage.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + + + task = httpClient.SendAsync(newMessage, cancellationToken); + responseMessage = await task.ConfigureAwait(false); + } + await responseMessage.Content.LoadIntoBufferAsync().ConfigureAwait(false); #if NET5_0_OR_GREATER var stream = await responseMessage.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);