Skip to content

Commit 7ee17d5

Browse files
committed
detect Cloudflare errors in UnknownError messaging
1 parent c4a40ea commit 7ee17d5

2 files changed

Lines changed: 21 additions & 5 deletions

File tree

__tests__/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ describe('execute', () => {
398398
expect(upstream.status).toEqual(500)
399399
expect(upstream.context.body).toEqual('<html>Bad Gateway</html>')
400400
expect(upstream.context.status).toEqual(500)
401-
expect(upstream.message).toMatch(/Expected a JSON response/)
401+
expect(upstream.message).toMatch(/Expected JSON response/)
402402
}
403403
})
404404

src/index.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ export { format } from './sanitization.js'
55
export { hex } from './text.js'
66
import { Version } from './version.js'
77

8+
// Cloudflare Workers sets navigator.userAgent to 'Cloudflare-Workers' when the
9+
// global_navigator compatibility flag is enabled (default since 2022-03-21).
10+
// https://developers.cloudflare.com/workers/configuration/compatibility-flags/#global-navigator
11+
const isCloudflareWorker = typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers'
12+
813
type Row<T extends ExecuteAs = 'object'> = T extends 'array' ? any[] : T extends 'object' ? Record<string, any> : never
914

1015
interface VitessError {
@@ -367,10 +372,21 @@ async function postJSON<T>(config: Config, fetch: Fetch, url: string | URL, body
367372
headers
368373
}
369374

370-
throw new UnknownError(
371-
`Expected a JSON response from the database API but received: HTTP ${response.status} ${response.statusText}`,
372-
context
373-
)
375+
// Cloudflare uses HTTP 520-530 for its own errors. These are never from the database API.
376+
// https://developers.cloudflare.com/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors/
377+
const isCloudflareStatusCode = response.status >= 520 && response.status <= 530
378+
379+
// Inside a Worker, any non-JSON response is from Cloudflare's infrastructure,
380+
// since the database API exclusively returns JSON responses.
381+
const isCloudflareError = isCloudflareStatusCode || isCloudflareWorker
382+
383+
const status = response.statusText ? `${response.status} ${response.statusText}` : `${response.status}`
384+
385+
const message = isCloudflareError
386+
? `Cloudflare error: HTTP ${status} (not a database error)`
387+
: `Expected JSON response from database API, got HTTP ${status}`
388+
389+
throw new UnknownError(message, context)
374390
}
375391

376392
export function connect(config: Config): Connection {

0 commit comments

Comments
 (0)