fix: remove trailing slash or space before constructing s3 uri (#516)

Closes #496
This commit is contained in:
Nico 2026-02-14 14:18:36 +01:00 committed by GitHub
parent d53b24bfb4
commit 39ae0cfe6d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 111 additions and 3 deletions

View file

@ -0,0 +1,106 @@
import { describe, expect, test } from "bun:test";
import { buildRepoUrl } from "./restic";
describe("buildRepoUrl", () => {
describe("S3 backend", () => {
test("should build URL without trailing slash", () => {
const config = {
backend: "s3" as const,
endpoint: "https://s3.amazonaws.com",
bucket: "my-bucket",
accessKeyId: "test",
secretAccessKey: "test",
};
expect(buildRepoUrl(config)).toBe("s3:https://s3.amazonaws.com/my-bucket");
});
test("should trim trailing slash from endpoint", () => {
const config = {
backend: "s3" as const,
endpoint: "https://s3.xxxxxxxxx.net/",
bucket: "backup",
accessKeyId: "test",
secretAccessKey: "test",
};
expect(buildRepoUrl(config)).toBe("s3:https://s3.xxxxxxxxx.net/backup");
});
test("should trim trailing whitespace from endpoint", () => {
const config = {
backend: "s3" as const,
endpoint: "https://s3.amazonaws.com/ ",
bucket: "my-bucket",
accessKeyId: "test",
secretAccessKey: "test",
};
expect(buildRepoUrl(config)).toBe("s3:https://s3.amazonaws.com/my-bucket");
});
test("should trim leading and trailing whitespace from endpoint", () => {
const config = {
backend: "s3" as const,
endpoint: " https://s3.amazonaws.com/ ",
bucket: "my-bucket",
accessKeyId: "test",
secretAccessKey: "test",
};
expect(buildRepoUrl(config)).toBe("s3:https://s3.amazonaws.com/my-bucket");
});
});
describe("R2 backend", () => {
test("should build URL without trailing slash", () => {
const config = {
backend: "r2" as const,
endpoint: "https://myaccount.r2.cloudflarestorage.com",
bucket: "my-bucket",
accessKeyId: "test",
secretAccessKey: "test",
};
expect(buildRepoUrl(config)).toBe("s3:myaccount.r2.cloudflarestorage.com/my-bucket");
});
test("should trim trailing slash from endpoint", () => {
const config = {
backend: "r2" as const,
endpoint: "https://myaccount.r2.cloudflarestorage.com/",
bucket: "backup",
accessKeyId: "test",
secretAccessKey: "test",
};
expect(buildRepoUrl(config)).toBe("s3:myaccount.r2.cloudflarestorage.com/backup");
});
test("should strip protocol and trailing slash", () => {
const config = {
backend: "r2" as const,
endpoint: "https://myaccount.r2.cloudflarestorage.com/",
bucket: "my-bucket",
accessKeyId: "test",
secretAccessKey: "test",
};
expect(buildRepoUrl(config)).toBe("s3:myaccount.r2.cloudflarestorage.com/my-bucket");
});
test("should trim whitespace and strip protocol", () => {
const config = {
backend: "r2" as const,
endpoint: " https://myaccount.r2.cloudflarestorage.com/ ",
bucket: "my-bucket",
accessKeyId: "test",
secretAccessKey: "test",
};
expect(buildRepoUrl(config)).toBe("s3:myaccount.r2.cloudflarestorage.com/my-bucket");
});
});
describe("other backends", () => {
test("should build local repository URL", () => {
const config = {
backend: "local" as const,
path: "/path/to/repo",
};
expect(buildRepoUrl(config)).toBe("/path/to/repo");
});
});
});

View file

@ -43,10 +43,12 @@ export const buildRepoUrl = (config: RepositoryConfig): string => {
switch (config.backend) {
case "local":
return config.path;
case "s3":
return `s3:${config.endpoint}/${config.bucket}`;
case "s3": {
const endpoint = config.endpoint.trim().replace(/\/$/, "");
return `s3:${endpoint}/${config.bucket}`;
}
case "r2": {
const endpoint = config.endpoint.replace(/^https?:\/\//, "");
const endpoint = config.endpoint.trim().replace(/^https?:\/\//, "").replace(/\/$/, "");
return `s3:${endpoint}/${config.bucket}`;
}
case "gcs":