From f6ac1f2ad481a5cd4fe64e0ce61c08875853d619 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 09:49:57 +0000 Subject: [PATCH] fix(api): answer 200 when a key-value store record is overwritten Storing a record answered 201 whether the key was new or not. An overwrite now answers 200, so a client can tell a first write from an update. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_017ocuAL43YR6VPaBRrRfBbL --- src/api/routes/key-value-stores.ts | 7 +++++-- test/integration/key-value-stores.test.ts | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/api/routes/key-value-stores.ts b/src/api/routes/key-value-stores.ts index 8733089..167967b 100644 --- a/src/api/routes/key-value-stores.ts +++ b/src/api/routes/key-value-stores.ts @@ -98,9 +98,12 @@ export function mountKeyValueStoreOperations(router: Router, basePath: string, r const store = await openKeyValueStore(record.id); const contentType = req.header('content-type') ?? 'application/octet-stream'; const body = Buffer.isBuffer(req.body) ? req.body : Buffer.alloc(0); - await store.setValue(req.params.recordKey as string, body, { contentType }); + const recordKey = req.params.recordKey as string; + // A record is created once and overwritten afterwards; the status tells the client which. + const existed = (await store.getRecord(recordKey)) !== null; + await store.setValue(recordKey, body, { contentType }); await touchStorage(record.id); - res.status(201).end(); + res.status(existed ? 200 : 201).end(); }); router.put(`${basePath}/records/:recordKey`, setRecord); // The spec's "Store record (POST)": an alias of the PUT, for clients that cannot send PUT. diff --git a/test/integration/key-value-stores.test.ts b/test/integration/key-value-stores.test.ts index e2ffe4f..c757888 100644 --- a/test/integration/key-value-stores.test.ts +++ b/test/integration/key-value-stores.test.ts @@ -66,13 +66,13 @@ describe('key-value-stores API (via real apify-client)', () => { expect(posted.status).toBe(201); expect((await store.getRecord('OUTPUT'))?.value).toEqual({ via: 'post' }); - // Overwrites like PUT does, keeping the content type it was sent with. + // Overwrites like PUT does, keeping the content type it was sent with; an overwrite is a 200. const overwritten = await fetch(`${server.baseUrl}/v2/key-value-stores/${id}/records/OUTPUT`, { method: 'POST', headers: { Authorization: `Bearer ${server.token}`, 'Content-Type': 'text/plain' }, body: 'plain', }); - expect(overwritten.status).toBe(201); + expect(overwritten.status).toBe(200); const record = await store.getRecord('OUTPUT'); expect(record?.value).toBe('plain'); expect(record?.contentType).toMatch(/^text\/plain/);