fix(worker): preserve API base path in Online Inbox client
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) <noreply@anthropic.com>
This commit is contained in:
@@ -31,14 +31,14 @@ public sealed class OnlineInboxApiClient : IOnlineInboxApi
|
|||||||
|
|
||||||
public async Task PutListsAsync(IReadOnlyList<RemoteList> lists, CancellationToken ct = default)
|
public async Task PutListsAsync(IReadOnlyList<RemoteList> 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);
|
using var resp = await _http.SendAsync(req, ct);
|
||||||
await EnsureSuccessAsync(resp, ct);
|
await EnsureSuccessAsync(resp, ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IReadOnlyList<RemoteTask>> GetUnimportedTasksAsync(CancellationToken ct = default)
|
public async Task<IReadOnlyList<RemoteTask>> 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);
|
using var resp = await _http.SendAsync(req, ct);
|
||||||
await EnsureSuccessAsync(resp, ct);
|
await EnsureSuccessAsync(resp, ct);
|
||||||
var result = await resp.Content.ReadFromJsonAsync<List<RemoteTask>>(ct);
|
var result = await resp.Content.ReadFromJsonAsync<List<RemoteTask>>(ct);
|
||||||
@@ -47,14 +47,14 @@ public sealed class OnlineInboxApiClient : IOnlineInboxApi
|
|||||||
|
|
||||||
public async Task MarkImportedAsync(string id, CancellationToken ct = default)
|
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);
|
using var resp = await _http.SendAsync(req, ct);
|
||||||
await EnsureSuccessAsync(resp, ct);
|
await EnsureSuccessAsync(resp, ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PutMirrorAsync(IReadOnlyList<MirrorTask> tasks, CancellationToken ct = default)
|
public async Task PutMirrorAsync(IReadOnlyList<MirrorTask> 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);
|
using var resp = await _http.SendAsync(req, ct);
|
||||||
await EnsureSuccessAsync(resp, ct);
|
await EnsureSuccessAsync(resp, ct);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ public sealed class OnlineInboxApiClientTests
|
|||||||
private static (OnlineInboxApiClient Client, StubHandler Handler) Build(string? token = "test-token")
|
private static (OnlineInboxApiClient Client, StubHandler Handler) Build(string? token = "test-token")
|
||||||
{
|
{
|
||||||
var handler = new StubHandler();
|
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);
|
var auth = new StaticTokenAuthProvider(token);
|
||||||
return (new OnlineInboxApiClient(http, auth), handler);
|
return (new OnlineInboxApiClient(http, auth), handler);
|
||||||
}
|
}
|
||||||
@@ -45,7 +47,7 @@ public sealed class OnlineInboxApiClientTests
|
|||||||
|
|
||||||
Assert.Single(handler.Requests);
|
Assert.Single(handler.Requests);
|
||||||
Assert.Equal(HttpMethod.Put, handler.Requests[0].Method);
|
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]
|
[Fact]
|
||||||
@@ -98,7 +100,7 @@ public sealed class OnlineInboxApiClientTests
|
|||||||
await client.MarkImportedAsync("task-id-123");
|
await client.MarkImportedAsync("task-id-123");
|
||||||
|
|
||||||
Assert.Equal(HttpMethod.Post, handler.Requests[0].Method);
|
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 ----
|
// ---- PutMirrorAsync ----
|
||||||
@@ -110,7 +112,7 @@ public sealed class OnlineInboxApiClientTests
|
|||||||
await client.PutMirrorAsync([new MirrorTask("id1", "l1", "T", null)]);
|
await client.PutMirrorAsync([new MirrorTask("id1", "l1", "T", null)]);
|
||||||
|
|
||||||
Assert.Equal(HttpMethod.Put, handler.Requests[0].Method);
|
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 ----
|
// ---- 401 handling ----
|
||||||
|
|||||||
Reference in New Issue
Block a user