From b81f78077ba2a45257e32df8a92527de2a814abc Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sun, 30 Jun 2024 14:22:55 +0200 Subject: [PATCH] Fixed: send absolute/relative URL in location header, depending on options.UseRelativeLinks --- .../Controllers/BaseJsonApiController.cs | 13 ++++++++++++- .../Links/AbsoluteLinksWithNamespaceTests.cs | 2 ++ .../Links/AbsoluteLinksWithoutNamespaceTests.cs | 2 ++ .../Links/RelativeLinksWithNamespaceTests.cs | 2 ++ .../Links/RelativeLinksWithoutNamespaceTests.cs | 2 ++ .../ReadWrite/Creating/CreateResourceTests.cs | 4 ++-- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs index fb3cd2bd2d..9cbc30dead 100644 --- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs +++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs @@ -3,6 +3,8 @@ using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Services; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; @@ -207,7 +209,7 @@ public virtual async Task PostAsync([FromBody] TResource resource TResource? newResource = await _create.CreateAsync(resource, cancellationToken); string resourceId = (newResource ?? resource).StringId!; - string locationUrl = HttpContext.Request.Path.Add($"/{resourceId}"); + string locationUrl = GetLocationUrl(resourceId); if (newResource == null) { @@ -218,6 +220,15 @@ public virtual async Task PostAsync([FromBody] TResource resource return Created(locationUrl, newResource); } + private string GetLocationUrl(string resourceId) + { + PathString locationPath = HttpContext.Request.Path.Add($"/{resourceId}"); + + return _options.UseRelativeLinks + ? UriHelper.BuildRelative(HttpContext.Request.PathBase, locationPath) + : UriHelper.BuildAbsolute(HttpContext.Request.Scheme, HttpContext.Request.Host, HttpContext.Request.PathBase, locationPath); + } + /// /// Adds resources to a to-many relationship. Example: value.Links.Related.Should().Be($"{photoLink}/album"); }); }); + + httpResponse.Headers.Location.Should().Be(albumLink); } [Fact] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs index 6ba9636128..6efcf034fa 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/AbsoluteLinksWithoutNamespaceTests.cs @@ -394,6 +394,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => value.Links.Related.Should().Be($"{photoLink}/album"); }); }); + + httpResponse.Headers.Location.Should().Be(albumLink); } [Fact] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs index 604f9c3e90..fbb642844f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithNamespaceTests.cs @@ -394,6 +394,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => value.Links.Related.Should().Be($"{photoLink}/album"); }); }); + + httpResponse.Headers.Location.Should().Be(albumLink); } [Fact] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs index 6ce1effd7c..f767b0cca6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Links/RelativeLinksWithoutNamespaceTests.cs @@ -394,6 +394,8 @@ await _testContext.RunOnDatabaseAsync(async dbContext => value.Links.Related.Should().Be($"{photoLink}/album"); }); }); + + httpResponse.Headers.Location.Should().Be(albumLink); } [Fact] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs index 917f10be85..39af545d0c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs @@ -58,7 +58,7 @@ public async Task Sets_location_header_for_created_resource() httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); string newWorkItemId = responseDocument.Data.SingleValue.ShouldNotBeNull().Id.ShouldNotBeNull(); - httpResponse.Headers.Location.Should().Be($"/workItems/{newWorkItemId}"); + httpResponse.Headers.Location.Should().Be($"http://localhost/workItems/{newWorkItemId}"); responseDocument.Links.ShouldNotBeNull(); responseDocument.Links.Self.Should().Be("http://localhost/workItems/"); @@ -66,7 +66,7 @@ public async Task Sets_location_header_for_created_resource() responseDocument.Data.SingleValue.ShouldNotBeNull(); responseDocument.Data.SingleValue.Links.ShouldNotBeNull(); - responseDocument.Data.SingleValue.Links.Self.Should().Be($"http://localhost{httpResponse.Headers.Location}"); + responseDocument.Data.SingleValue.Links.Self.Should().Be($"{httpResponse.Headers.Location}"); } [Fact]