From 1951228315edc1932b49510ed72d87cbd67a1792 Mon Sep 17 00:00:00 2001 From: Gruak <43846312+Gruak@users.noreply.github.com> Date: Sun, 4 Aug 2024 19:36:27 +0200 Subject: [PATCH 1/6] feat(openapi-fetch): baseUrl per request --- packages/openapi-fetch/src/index.d.ts | 4 ++ packages/openapi-fetch/src/index.js | 19 +++++++-- packages/openapi-fetch/test/index.test.ts | 50 +++++++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/packages/openapi-fetch/src/index.d.ts b/packages/openapi-fetch/src/index.d.ts index 2ba91147f..1be856564 100644 --- a/packages/openapi-fetch/src/index.d.ts +++ b/packages/openapi-fetch/src/index.d.ts @@ -109,6 +109,7 @@ export type FetchResponse = export type RequestOptions = ParamsOption & RequestBodyOption & { + baseUrl?: string; querySerializer?: QuerySerializer | QuerySerializerOptions; bodySerializer?: BodySerializer; parseAs?: ParseAs; @@ -253,3 +254,6 @@ export declare function createFinalURL( /** Merge headers a and b, with b taking priority */ export declare function mergeHeaders(...allHeaders: (HeadersOptions | undefined)[]): Headers; + +/** Remove trailing slash from url */ +export declare function removeTrailingSlash(url: string): string; diff --git a/packages/openapi-fetch/src/index.js b/packages/openapi-fetch/src/index.js index e878ef0b8..66202baed 100644 --- a/packages/openapi-fetch/src/index.js +++ b/packages/openapi-fetch/src/index.js @@ -40,9 +40,7 @@ export default function createClient(clientOptions) { headers: baseHeaders, ...baseOptions } = { ...clientOptions }; - if (baseUrl.endsWith("/")) { - baseUrl = baseUrl.substring(0, baseUrl.length - 1); - } + baseUrl = removeTrailingSlash(baseUrl); baseHeaders = mergeHeaders(DEFAULT_HEADERS, baseHeaders); const middlewares = []; @@ -53,6 +51,7 @@ export default function createClient(clientOptions) { */ async function coreFetch(schemaPath, fetchOptions) { const { + baseUrl: localBaseUrl, fetch = baseFetch, headers, params = {}, @@ -61,6 +60,9 @@ export default function createClient(clientOptions) { bodySerializer = globalBodySerializer ?? defaultBodySerializer, ...init } = fetchOptions || {}; + if (localBaseUrl) { + baseUrl = removeTrailingSlash(localBaseUrl); + } let querySerializer = typeof globalQuerySerializer === "function" @@ -484,3 +486,14 @@ export function mergeHeaders(...allHeaders) { } return finalHeaders; } + +/** + * Remove trailing slash from url + * @type {import("./index.js").removeTrailingSlash} + */ +export function removeTrailingSlash(url) { + if (url.endsWith("/")) { + return url.substring(0, url.length - 1); + } + return url; +} diff --git a/packages/openapi-fetch/test/index.test.ts b/packages/openapi-fetch/test/index.test.ts index 0055dcba7..83ac0df99 100644 --- a/packages/openapi-fetch/test/index.test.ts +++ b/packages/openapi-fetch/test/index.test.ts @@ -767,6 +767,29 @@ describe("client", () => { expect(getRequestUrl().href).toBe(toAbsoluteURL("/self")); }); + it("baseUrl per request", async () => { + const localBaseUrl = "https://api.foo.bar/v1"; + let client = createClient({ baseUrl }); + + const { getRequestUrl } = useMockRequestHandler({ + baseUrl: localBaseUrl, + method: "get", + path: "/self", + status: 200, + body: { message: "OK" }, + }); + + await client.GET("/self", { baseUrl: localBaseUrl }); + + // assert baseUrl and path mesh as expected + expect(getRequestUrl().href).toBe(toAbsoluteURL("/self", localBaseUrl)); + + client = createClient({ baseUrl }); + await client.GET("/self", { baseUrl: localBaseUrl }); + // assert trailing '/' was removed + expect(getRequestUrl().href).toBe(toAbsoluteURL("/self", localBaseUrl)); + }); + describe("headers", () => { it("persist", async () => { const headers: HeadersInit = { Authorization: "Bearer secrettoken" }; @@ -1272,6 +1295,33 @@ describe("client", () => { expect(req.headers.get("onFetch")).toBe("exists"); expect(req.headers.get("onRequest")).toBe("exists"); }); + + it("baseUrl can be overriden", async () => { + useMockRequestHandler({ + baseUrl: "https://api.foo.bar/v1/", + method: "get", + path: "/self", + status: 200, + body: {}, + }); + + let requestBaseUrl = ""; + + const client = createClient({ + baseUrl, + }); + client.use({ + onRequest({ options }) { + requestBaseUrl = options.baseUrl; + return undefined; + }, + }); + + await client.GET("/self", { + baseUrl: "https://api.foo.bar/v1/" + }); + expect(requestBaseUrl).toBe("https://api.foo.bar/v1"); + }); }); }); From 024a8f467090d0f1740effdf5098634bff6bd5ce Mon Sep 17 00:00:00 2001 From: Gruak <43846312+Gruak@users.noreply.github.com> Date: Sun, 4 Aug 2024 20:10:30 +0200 Subject: [PATCH 2/6] chore: update docs --- docs/openapi-fetch/api.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/openapi-fetch/api.md b/docs/openapi-fetch/api.md index 0a337aaae..00923d233 100644 --- a/docs/openapi-fetch/api.md +++ b/docs/openapi-fetch/api.md @@ -36,6 +36,7 @@ client.GET("/my-url", options); | `querySerializer` | QuerySerializer | (optional) Provide a [querySerializer](#queryserializer) | | `bodySerializer` | BodySerializer | (optional) Provide a [bodySerializer](#bodyserializer) | | `parseAs` | `"json"` \| `"text"` \| `"arrayBuffer"` \| `"blob"` \| `"stream"` | (optional) Parse the response using [a built-in instance method](https://developer.mozilla.org/en-US/docs/Web/API/Response#instance_methods) (default: `"json"`). `"stream"` skips parsing altogether and returns the raw stream. | +| `baseUrl` | `string` | Prefix the fetch URL with this option (e.g. "https://myapi.dev/v1/") | | `fetch` | `fetch` | Fetch instance used for requests (default: fetch from `createClient`) | | `middleware` | `Middleware[]` | [See docs](/openapi-fetch/middleware-auth) | | (Fetch options) | | Any valid fetch option (`headers`, `mode`, `cache`, `signal`, …) ([docs](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options)) | From d639693621d9138a08dd3c014a50049baa9fa0b9 Mon Sep 17 00:00:00 2001 From: Gruak <43846312+Gruak@users.noreply.github.com> Date: Sun, 4 Aug 2024 20:18:49 +0200 Subject: [PATCH 3/6] chore: add changeset --- .changeset/happy-singers-fry.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/happy-singers-fry.md diff --git a/.changeset/happy-singers-fry.md b/.changeset/happy-singers-fry.md new file mode 100644 index 000000000..a2d9d7b38 --- /dev/null +++ b/.changeset/happy-singers-fry.md @@ -0,0 +1,5 @@ +--- +"openapi-fetch": minor +--- + +feat: set baseUrl per request From 231d5140a56a1922eb738bda6b42efe60d2af1ac Mon Sep 17 00:00:00 2001 From: Gruak <43846312+Gruak@users.noreply.github.com> Date: Sun, 4 Aug 2024 20:49:42 +0200 Subject: [PATCH 4/6] fix(openapi-fetch): lint error --- packages/openapi-fetch/test/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/openapi-fetch/test/index.test.ts b/packages/openapi-fetch/test/index.test.ts index 83ac0df99..37df7b9f2 100644 --- a/packages/openapi-fetch/test/index.test.ts +++ b/packages/openapi-fetch/test/index.test.ts @@ -1318,7 +1318,7 @@ describe("client", () => { }); await client.GET("/self", { - baseUrl: "https://api.foo.bar/v1/" + baseUrl: "https://api.foo.bar/v1/", }); expect(requestBaseUrl).toBe("https://api.foo.bar/v1"); }); From 5013327f1d537a23c93d422f0f00f41297ca7024 Mon Sep 17 00:00:00 2001 From: Gruak <43846312+Gruak@users.noreply.github.com> Date: Sat, 10 Aug 2024 18:42:13 +0200 Subject: [PATCH 5/6] Update .changeset/happy-singers-fry.md Co-authored-by: Martin Paucot --- .changeset/happy-singers-fry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/happy-singers-fry.md b/.changeset/happy-singers-fry.md index a2d9d7b38..16d22fb3b 100644 --- a/.changeset/happy-singers-fry.md +++ b/.changeset/happy-singers-fry.md @@ -2,4 +2,4 @@ "openapi-fetch": minor --- -feat: set baseUrl per request +Allow specifying baseUrl per request From 21a5e4cc646a685b5e5956b0ec5ff1a36049464c Mon Sep 17 00:00:00 2001 From: Gruak <43846312+Gruak@users.noreply.github.com> Date: Sat, 10 Aug 2024 18:46:27 +0200 Subject: [PATCH 6/6] test: fix typo --- packages/openapi-fetch/test/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/openapi-fetch/test/index.test.ts b/packages/openapi-fetch/test/index.test.ts index 37df7b9f2..484892bf1 100644 --- a/packages/openapi-fetch/test/index.test.ts +++ b/packages/openapi-fetch/test/index.test.ts @@ -1296,7 +1296,7 @@ describe("client", () => { expect(req.headers.get("onRequest")).toBe("exists"); }); - it("baseUrl can be overriden", async () => { + it("baseUrl can be overridden", async () => { useMockRequestHandler({ baseUrl: "https://api.foo.bar/v1/", method: "get",