From b163454ce2654ff0e10eadbd5c8af96b1ca63069 Mon Sep 17 00:00:00 2001 From: crayon <1104507145@qq.com> Date: Sun, 14 Dec 2025 17:09:16 +0800 Subject: [PATCH 1/2] fix(utils): trim trailing whitespace from base URLs (fixes #530) --- src/utils.url.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/utils.url.ts b/src/utils.url.ts index 5a725353..3d9538a6 100644 --- a/src/utils.url.ts +++ b/src/utils.url.ts @@ -38,11 +38,15 @@ export function joinURL(base?: string, path?: string): string { * Adds the base path to the input path, if it is not already present. */ export function withBase(input = "", base = ""): string { - if (!base || base === "/") { + if (!base) { + return input; + } + const cleanedBase = String(base).trim(); + if (cleanedBase === "/") { return input; } - const _base = withoutTrailingSlash(base); + const _base = withoutTrailingSlash(cleanedBase); if (input.startsWith(_base)) { return input; } @@ -51,11 +55,16 @@ export function withBase(input = "", base = ""): string { } function withoutTrailingSlash(path?: string): string { - if (!path || path === "/") { + if (!path) { + return "/"; + } + + const trimmed = path.trimEnd(); + if (trimmed === "/") { return "/"; } - return path[path.length - 1] === "/" ? path.slice(0, -1) : path; + return trimmed[trimmed.length - 1] === "/" ? trimmed.slice(0, -1) : trimmed; } /** From b124a2bf1337b13bbbdc0618dba561c5ba1deed3 Mon Sep 17 00:00:00 2001 From: crayon <1104507145@qq.com> Date: Sun, 14 Dec 2025 17:17:43 +0800 Subject: [PATCH 2/2] test: add regression for baseURL trailing CR (covers #530) --- test/index.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/index.test.ts b/test/index.test.ts index 5ac20b07..d4ce5fa4 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -116,6 +116,16 @@ describe("ofetch", () => { ); }); + it("baseURL with trailing CR", async () => { + expect( + await $fetch("/x?foo=123", { baseURL: getURL("url") + "\r" }) + ).to.equal("/url/x?foo=123"); + + expect(await $fetch("/x", { baseURL: getURL("url") + "\r" })).to.equal( + "/url/x" + ); + }); + it("stringifies posts body automatically", async () => { const { body } = await $fetch(getURL("post"), { method: "POST",