diff --git a/Refit.Tests/RequestBuilder.cs b/Refit.Tests/RequestBuilder.cs index 4c06cb9da..0ba4ca4a4 100644 --- a/Refit.Tests/RequestBuilder.cs +++ b/Refit.Tests/RequestBuilder.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.IO; @@ -9,7 +9,9 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; + using Microsoft.AspNetCore.WebUtilities; + using Xunit; namespace Refit.Tests @@ -1726,6 +1728,21 @@ public void GenericReturnTypeIsNotTaskOrObservableShouldThrow() ) ); } + + [Fact] + public void ShouldCaptureLastCharacterWhenRouteEndsWithConstant() + { + var fixture = new RequestBuilderImplementation(); + var factory = fixture.BuildRequestFactoryForMethod( + "GetWithParenthesis" + ); + var output = factory(["1"]); + + var uri = new Uri(new Uri("http://api/foo/bar/"), output.RequestUri); + + Assert.EndsWith(")", uri.PathAndQuery, StringComparison.Ordinal); + Assert.Contains("/foo/bar/(1)", uri.PathAndQuery, StringComparison.Ordinal); + } } [Headers("User-Agent: RefitTestClient", "Api-Version: 1")] @@ -1767,6 +1784,9 @@ Task FetchSomeStuffWithHardcodedAndOtherQueryParameters( [Get("/foo/bar/{id}?param1={id}¶m2={id}")] Task FetchSomeStuffWithTheSameId(int id); + [Get("/foo/bar/({id})")] + Task GetWithParenthesis(int id); + [Get("/foo/bar?param=first {id} and second {id}")] Task FetchSomeStuffWithTheIdInAParameterMultipleTimes(int id); diff --git a/Refit/RestMethodInfo.cs b/Refit/RestMethodInfo.cs index b87c8248d..bd3072bbe 100644 --- a/Refit/RestMethodInfo.cs +++ b/Refit/RestMethodInfo.cs @@ -27,7 +27,7 @@ Type ReturnType [DebuggerDisplay("{MethodInfo}")] internal class RestMethodInfoInternal { - private int HeaderCollectionParameterIndex { get; } + private int HeaderCollectionParameterIndex { get; } private string Name => MethodInfo.Name; public Type Type { get; } public MethodInfo MethodInfo { get; } @@ -47,7 +47,7 @@ internal class RestMethodInfoInternal public Dictionary> AttachmentNameMap { get; } public ParameterInfo[] ParameterInfoArray { get; } public Dictionary ParameterMap { get; } - public List FragmentPath { get ; set ; } + public List FragmentPath { get; set; } public Type ReturnType { get; set; } public Type ReturnResultType { get; set; } public Type DeserializedResultType { get; set; } @@ -167,7 +167,7 @@ public RestMethodInfoInternal( RestMethodInfo = new RestMethodInfo(Name, Type, MethodInfo, RelativePath, ReturnType!); CancellationToken = ctParam; - QueryUriFormat = methodInfo.GetCustomAttribute()?.UriFormat + QueryUriFormat = methodInfo.GetCustomAttribute()?.UriFormat ?? UriFormat.UriEscaped; IsApiResponse = @@ -201,7 +201,7 @@ static int GetHeaderCollectionParameterIndex(ParameterInfo[] parameterArray) if (param.ParameterType.IsAssignableFrom(typeof(IDictionary))) { // throw if there is already a HeaderCollection parameter - if(headerIndex >= 0) + if (headerIndex >= 0) throw new ArgumentException("Only one parameter can be a HeaderCollection parameter"); headerIndex = i; @@ -278,7 +278,7 @@ ParameterInfo[] parameterInfo if (parameterizedParts.Length == 0) { - if(string.IsNullOrEmpty(relativePath)) + if (string.IsNullOrEmpty(relativePath)) return (ret, []); return (ret, [ParameterFragment.Constant(relativePath)]); @@ -300,7 +300,7 @@ ParameterInfo[] parameterInfo var fragmentList = new List(); var index = 0; - foreach (var match in parameterizedParts) + foreach (var match in parameterizedParts) { // Add constant value from given http path if (match.Index != index) @@ -402,7 +402,7 @@ ParameterInfo[] parameterInfo } // add trailing string - if (index < relativePath.Length - 1) + if (index < relativePath.Length) { var trailingConstant = relativePath.Substring(index, relativePath.Length - index); fragmentList.Add(ParameterFragment.Constant(trailingConstant)); @@ -708,8 +708,8 @@ internal record struct ParameterFragment(string? Value, int ArgumentIndex, int P public bool IsDynamicRoute => ArgumentIndex >= 0 && PropertyIndex < 0; public bool IsObjectProperty => ArgumentIndex >= 0 && PropertyIndex >= 0; - public static ParameterFragment Constant(string value) => new (value, -1, -1); - public static ParameterFragment Dynamic(int index) => new (null, index, -1); - public static ParameterFragment DynamicObject(int index, int propertyIndex) => new (null, index, propertyIndex); + public static ParameterFragment Constant(string value) => new(value, -1, -1); + public static ParameterFragment Dynamic(int index) => new(null, index, -1); + public static ParameterFragment DynamicObject(int index, int propertyIndex) => new(null, index, propertyIndex); } }