From 8b347de1318eb15dc86b9c189c5b7b53c7329d64 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Wed, 10 Jun 2026 10:35:30 +0200 Subject: [PATCH] fix(worker): preserve API base path in Online Inbox client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The API base URL is https://claudedo.kuns.dev/api — leading-slash request paths discarded the /api segment. Use relative paths so they nest under the base. Tests now use a /api/ base to guard the regression. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/ClaudeDo.Worker/Online/OnlineInboxApiClient.cs | 8 ++++---- .../Online/OnlineInboxApiClientTests.cs | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ClaudeDo.Worker/Online/OnlineInboxApiClient.cs b/src/ClaudeDo.Worker/Online/OnlineInboxApiClient.cs index a5a8377..1444288 100644 --- a/src/ClaudeDo.Worker/Online/OnlineInboxApiClient.cs +++ b/src/ClaudeDo.Worker/Online/OnlineInboxApiClient.cs @@ -31,14 +31,14 @@ public sealed class OnlineInboxApiClient : IOnlineInboxApi public async Task PutListsAsync(IReadOnlyList lists, CancellationToken ct = default) { - using var req = await BuildAsync(HttpMethod.Put, "/lists", lists, ct); + using var req = await BuildAsync(HttpMethod.Put, "lists", lists, ct); using var resp = await _http.SendAsync(req, ct); await EnsureSuccessAsync(resp, ct); } public async Task> GetUnimportedTasksAsync(CancellationToken ct = default) { - using var req = await BuildAsync(HttpMethod.Get, "/tasks?imported=false", null, ct); + using var req = await BuildAsync(HttpMethod.Get, "tasks?imported=false", null, ct); using var resp = await _http.SendAsync(req, ct); await EnsureSuccessAsync(resp, ct); var result = await resp.Content.ReadFromJsonAsync>(ct); @@ -47,14 +47,14 @@ public sealed class OnlineInboxApiClient : IOnlineInboxApi public async Task MarkImportedAsync(string id, CancellationToken ct = default) { - using var req = await BuildAsync(HttpMethod.Post, $"/tasks/{Uri.EscapeDataString(id)}/imported", null, ct); + using var req = await BuildAsync(HttpMethod.Post, $"tasks/{Uri.EscapeDataString(id)}/imported", null, ct); using var resp = await _http.SendAsync(req, ct); await EnsureSuccessAsync(resp, ct); } public async Task PutMirrorAsync(IReadOnlyList tasks, CancellationToken ct = default) { - using var req = await BuildAsync(HttpMethod.Put, "/tasks/mirror", tasks, ct); + using var req = await BuildAsync(HttpMethod.Put, "tasks/mirror", tasks, ct); using var resp = await _http.SendAsync(req, ct); await EnsureSuccessAsync(resp, ct); } diff --git a/tests/ClaudeDo.Worker.Tests/Online/OnlineInboxApiClientTests.cs b/tests/ClaudeDo.Worker.Tests/Online/OnlineInboxApiClientTests.cs index 0a87891..b53cb05 100644 --- a/tests/ClaudeDo.Worker.Tests/Online/OnlineInboxApiClientTests.cs +++ b/tests/ClaudeDo.Worker.Tests/Online/OnlineInboxApiClientTests.cs @@ -30,7 +30,9 @@ public sealed class OnlineInboxApiClientTests private static (OnlineInboxApiClient Client, StubHandler Handler) Build(string? token = "test-token") { var handler = new StubHandler(); - var http = new HttpClient(handler) { BaseAddress = new Uri("https://inbox.example.com/") }; + // Base address carries a path segment (/api) — requests must nest under it, + // so the client uses relative paths without a leading slash. + var http = new HttpClient(handler) { BaseAddress = new Uri("https://inbox.example.com/api/") }; var auth = new StaticTokenAuthProvider(token); return (new OnlineInboxApiClient(http, auth), handler); } @@ -45,7 +47,7 @@ public sealed class OnlineInboxApiClientTests Assert.Single(handler.Requests); Assert.Equal(HttpMethod.Put, handler.Requests[0].Method); - Assert.Equal("/lists", handler.Requests[0].RequestUri!.AbsolutePath); + Assert.Equal("/api/lists", handler.Requests[0].RequestUri!.AbsolutePath); } [Fact] @@ -98,7 +100,7 @@ public sealed class OnlineInboxApiClientTests await client.MarkImportedAsync("task-id-123"); Assert.Equal(HttpMethod.Post, handler.Requests[0].Method); - Assert.Equal("/tasks/task-id-123/imported", handler.Requests[0].RequestUri!.AbsolutePath); + Assert.Equal("/api/tasks/task-id-123/imported", handler.Requests[0].RequestUri!.AbsolutePath); } // ---- PutMirrorAsync ---- @@ -110,7 +112,7 @@ public sealed class OnlineInboxApiClientTests await client.PutMirrorAsync([new MirrorTask("id1", "l1", "T", null)]); Assert.Equal(HttpMethod.Put, handler.Requests[0].Method); - Assert.Equal("/tasks/mirror", handler.Requests[0].RequestUri!.AbsolutePath); + Assert.Equal("/api/tasks/mirror", handler.Requests[0].RequestUri!.AbsolutePath); } // ---- 401 handling ----