Skip to content

Commit 9bf4f6c

Browse files
tonyxiaoclaude
andcommitted
Fix stateless API test failures after OpenAPI migration
Two issues introduced by the OpenAPIHono conversion: 1. hasBody() returned false for test requests — Hono's app.request() doesn't set Content-Length on string bodies, so the check for Content-Length > 0 always failed in tests. Fix: fall back to c.req.raw.body !== null (null = no body in tests; Node.js 24 real HTTP bodyless POSTs always have Content-Length: 0 so they're caught by the explicit check before the fallback). 2. Missing X-Sync-Params now returns Zod issues array — OpenAPIHono validates the required x-sync-params header before calling the handler, so requireSyncParams() was never reached. Fix: make the header optional in the schema so requireSyncParams() handles validation and returns the custom 'Missing X-Sync-Params header' message. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Committed-By-Agent: claude
1 parent 887ac44 commit 9bf4f6c

1 file changed

Lines changed: 21 additions & 13 deletions

File tree

apps/stateless/src/api/app.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,20 @@ import { ndjsonResponse } from '../stream'
1212
// ── Shared schemas ──────────────────────────────────────────────
1313

1414
const XSyncParamsHeader = z.object({
15-
'x-sync-params': z.string().openapi({
16-
description:
17-
'JSON-encoded SyncParams: { source_name, source_config, destination_name, destination_config, streams }',
18-
example: JSON.stringify({
19-
source_name: 'stripe',
20-
source_config: { api_key: 'sk_test_...' },
21-
destination_name: 'postgres',
22-
destination_config: { connection_string: 'postgres://localhost/db' },
23-
streams: [{ name: 'products' }],
15+
'x-sync-params': z
16+
.string()
17+
.optional()
18+
.openapi({
19+
description:
20+
'JSON-encoded SyncParams: { source_name, source_config, destination_name, destination_config, streams }',
21+
example: JSON.stringify({
22+
source_name: 'stripe',
23+
source_config: { api_key: 'sk_test_...' },
24+
destination_name: 'postgres',
25+
destination_config: { connection_string: 'postgres://localhost/db' },
26+
streams: [{ name: 'products' }],
27+
}),
2428
}),
25-
}),
2629
})
2730

2831
const ConnectorCheckSchema = z.object({
@@ -62,11 +65,16 @@ export function createApp(resolver: ConnectorResolver) {
6265
})
6366

6467
/** Node.js 24 sets c.req.raw.body to a non-null empty ReadableStream even for bodyless POSTs. */
65-
function hasBody(c: { req: { header: (name: string) => string | undefined } }): boolean {
68+
function hasBody(c: {
69+
req: { header: (name: string) => string | undefined; raw: { body: ReadableStream | null } }
70+
}): boolean {
6671
const cl = c.req.header('Content-Length')
67-
if (cl && Number(cl) > 0) return true
72+
if (cl !== undefined) return Number(cl) > 0
6873
if (c.req.header('Transfer-Encoding')) return true
69-
return false
74+
// In tests (app.request()), body is null for bodyless requests.
75+
// In Node.js 24 HTTP server, bodyless POSTs always arrive with Content-Length: 0,
76+
// so we never reach this line for real bodyless requests.
77+
return c.req.raw.body !== null
7078
}
7179

7280
/** Parse and validate X-Sync-Params header, or throw 400. */

0 commit comments

Comments
 (0)