From 103ec216f4d0a4fb85e65ea975bb605553d49486 Mon Sep 17 00:00:00 2001 From: Nicolas Ayral Seydoux Date: Tue, 2 Jul 2024 11:38:37 +0200 Subject: [PATCH] Add support for relative URLs --- src/http/httpError.test.ts | 32 +++++++++++++++++++++++++++++++- src/http/problemDetails.ts | 8 ++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/http/httpError.test.ts b/src/http/httpError.test.ts index 66944e1..1aa201a 100644 --- a/src/http/httpError.test.ts +++ b/src/http/httpError.test.ts @@ -18,7 +18,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -import { describe, it, expect } from "@jest/globals"; +import { describe, it, expect, jest } from "@jest/globals"; import { ClientHttpError } from "./httpError"; import { mockProblemDetails } from "./problemDetails.mock"; import { @@ -189,4 +189,34 @@ describe("ClientHttpError", () => { new ClientHttpError(response, "Not important", "Some error message"); }).toThrow(InruptClientError); }); + + it("supports relative URLs for type and instance", () => { + const responseUrl = "https://example.org/resource"; + const relativeTypeUrl = "../type"; + const relativeInstanceUrl = "../instance"; + const response = new Response(undefined, { + status: 400, + statusText: "Bad Request", + headers: new Headers({ + "Content-Type": "application/problem+json", + }), + }); + jest.spyOn(response, "url", "get").mockReturnValue(responseUrl); + const { problemDetails: mockedProblemDetails } = mockProblemDetails({}); + const error = new ClientHttpError( + response, + JSON.stringify({ + ...mockedProblemDetails, + type: relativeTypeUrl, + instance: relativeInstanceUrl, + }), + "Some error message", + ); + expect(error.problemDetails.type.href).toStrictEqual( + new URL(relativeTypeUrl, responseUrl).href, + ); + expect(error.problemDetails.instance?.href).toStrictEqual( + new URL(relativeInstanceUrl, responseUrl).href, + ); + }); }); diff --git a/src/http/problemDetails.ts b/src/http/problemDetails.ts index 4e82f4c..07fb31b 100644 --- a/src/http/problemDetails.ts +++ b/src/http/problemDetails.ts @@ -125,9 +125,9 @@ export function hasProblemDetails( return isProblemDetails((error as WithProblemDetails).problemDetails); } -function asUrl(url: string): URL | undefined { +function asUrl(url: string, base: string): URL | undefined { try { - return new URL(url); + return new URL(url, base); } catch { return undefined; } @@ -153,7 +153,7 @@ export function buildProblemDetails(response: ErrorResponse): ProblemDetails { if (response.headers.get("Content-Type") === PROBLEM_DETAILS_MIME) { try { const responseBody = JSON.parse(response.body); - const responseType = asUrl(responseBody.type); + const responseType = asUrl(responseBody.type, response.url); if (responseType !== undefined) { type = responseType; } @@ -166,7 +166,7 @@ export function buildProblemDetails(response: ErrorResponse): ProblemDetails { if (typeof responseBody.detail === "string") { detail = responseBody.detail; } - const responseInstance = asUrl(responseBody.instance); + const responseInstance = asUrl(responseBody.instance, response.url); if (responseInstance !== undefined) { instance = responseInstance; }