diff --git a/ReleaseNotes.md b/ReleaseNotes.md index c8d8ea3..6521321 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,6 @@ +### New in 1.0.3 (Released _) +* Allow relative link uri + ### New in 1.0 (Released 05/09/2018) * Upgrade packages to netstandard diff --git a/Version.props b/Version.props index a3a44a4..640e8c1 100644 --- a/Version.props +++ b/Version.props @@ -1,6 +1,6 @@ - 1.0.2 + 1.0.3 diff --git a/src/HalKit/HalClient.cs b/src/HalKit/HalClient.cs index 2f5a1fa..a224182 100644 --- a/src/HalKit/HalClient.cs +++ b/src/HalKit/HalClient.cs @@ -362,8 +362,13 @@ private async Task> SendRequestAsync( headers.Add("Accept", new[] { HalJsonMediaType }); } + + var uri = Configuration.AllowRelativeLinks + ? _linkResolver.ResolveLink(Configuration.RootEndpoint, link, parameters) + : _linkResolver.ResolveLink(link, parameters); + return await HttpConnection.SendRequestAsync( - _linkResolver.ResolveLink(link, parameters), + uri, method, body, headers, diff --git a/src/HalKit/HalKitConfiguration.cs b/src/HalKit/HalKitConfiguration.cs index c21f393..8fc257b 100644 --- a/src/HalKit/HalKitConfiguration.cs +++ b/src/HalKit/HalKitConfiguration.cs @@ -19,5 +19,7 @@ public HalKitConfiguration(Uri rootEndpoint) public Uri RootEndpoint { get; set; } public bool CaptureSynchronizationContext { get; set; } + + public bool AllowRelativeLinks { get; set; } } } diff --git a/src/HalKit/IHalKitConfiguration.cs b/src/HalKit/IHalKitConfiguration.cs index c64892d..9d468cb 100644 --- a/src/HalKit/IHalKitConfiguration.cs +++ b/src/HalKit/IHalKitConfiguration.cs @@ -18,5 +18,10 @@ public interface IHalKitConfiguration /// /// See http://blog.stephencleary.com/2012/02/async-and-await.html#avoiding-context. bool CaptureSynchronizationContext { get; set; } + + /// + /// Set whether relative links should be constructed from RootEndpoint + /// + bool AllowRelativeLinks { get; set; } } } diff --git a/src/HalKit/Services/ILinkResolver.cs b/src/HalKit/Services/ILinkResolver.cs index 38c74f6..656e209 100644 --- a/src/HalKit/Services/ILinkResolver.cs +++ b/src/HalKit/Services/ILinkResolver.cs @@ -16,5 +16,14 @@ public interface ILinkResolver /// Otherwise, the parameters are added to the href as query parameters. /// Uri ResolveLink(Link link, IDictionary parameters); + + /// + /// Resolves the href of the given with the given parameters to + /// get a . If is templated then the parameters + /// are applied in accordance with Uri Template Spec RFC6570 (http://tools.ietf.org/html/rfc6570). + /// Otherwise, the parameters are added to the href as query parameters. + /// If the link is a relative Uri, it is then merged with the given rootEndpoint. + /// + Uri ResolveLink(Uri rootEndpoint, Link link, IDictionary parameters); } } diff --git a/src/HalKit/Services/LinkResolver.cs b/src/HalKit/Services/LinkResolver.cs index 6025c9e..3776889 100644 --- a/src/HalKit/Services/LinkResolver.cs +++ b/src/HalKit/Services/LinkResolver.cs @@ -9,6 +9,19 @@ namespace HalKit.Services { public class LinkResolver : ILinkResolver { + public Uri ResolveLink(Uri rootEndpoint, Link link, IDictionary parameters) + { + Requires.ArgumentNotNull(link, nameof(link)); + + if (!link.HRef.Contains(rootEndpoint.AbsoluteUri)) + { + // Make new href from relative path (using absolute path as base) + link.HRef = rootEndpoint + link.HRef.Replace(rootEndpoint.AbsolutePath, ""); + } + + return ResolveLink(link, parameters); + } + public Uri ResolveLink(Link link, IDictionary parameters) { Requires.ArgumentNotNull(link, nameof(link)); @@ -20,7 +33,7 @@ public Uri ResolveLink(Link link, IDictionary parameters) if (!link.IsTemplated) { - return AppendParametersAsQueryParams(link, parameters); + return AppendParametersAsQueryParams(link.HRef, parameters); } var templateParameters = parameters.ToDictionary(kv => kv.Key, kv => (object) kv.Value); @@ -29,10 +42,10 @@ public Uri ResolveLink(Link link, IDictionary parameters) } private Uri AppendParametersAsQueryParams( - Link link, + string href, IEnumerable> parameters) { - var uriBuilder = new UriBuilder(link.HRef); + var uriBuilder = new UriBuilder(href); var existingQueryParameters = uriBuilder.Query.Replace("?", ""); if (!string.IsNullOrEmpty(existingQueryParameters) && !existingQueryParameters.EndsWith("&")) {