Skip to content

Commit f62e0c7

Browse files
committed
Move health endpoints to dedicated router
1 parent 1148321 commit f62e0c7

3 files changed

Lines changed: 69 additions & 56 deletions

File tree

README.md

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -157,25 +157,3 @@ console.log(users[0], users.count);
157157
- Token-based access control per database
158158
- Same API works from workers (OpenWorkers runtime)
159159

160-
## Status
161-
162-
### Implemented
163-
164-
- [x] Auth routes (GitHub OAuth, refresh)
165-
- [x] Users routes (profile)
166-
- [x] Workers routes (CRUD + name uniqueness check)
167-
- [x] Databases routes (CRUD + token management via Postgate)
168-
- [x] Environments routes (CRUD + values management)
169-
- [x] Domains routes (CRUD)
170-
- [x] Crons routes (CRUD)
171-
- [x] Zod input/output validation
172-
- [x] JWT authentication middleware
173-
- [x] Standalone binary compilation
174-
- [x] Postgate integration (HTTP-based Postgres access)
175-
176-
### TODO
177-
178-
- [ ] Error handling middleware (standardized error responses)
179-
- [ ] Rate limiting
180-
- [ ] Tests (unit + integration)
181-
- [ ] API documentation (OpenAPI/Swagger)

src/index.ts

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Hono } from 'hono';
22
import { cors } from 'hono/cors';
33
import { logger } from 'hono/logger';
4+
45
import { nodeEnv, port } from './config';
56
import { createAuthMiddleware, extractUser, errorHandler } from './middlewares/auth';
67
import authRoutes from './routes/auth';
@@ -15,9 +16,8 @@ import kv from './routes/kv';
1516
import storage from './routes/storage';
1617
import ai from './routes/ai';
1718
import apiKeys from './routes/api-keys';
19+
import health from './routes/health';
1820
import pkg from '../package.json';
19-
import { sql } from './services/db/client';
20-
import { WasmCron } from '@openworkers/croner-wasm';
2121

2222
export const app = new Hono();
2323

@@ -32,38 +32,8 @@ if (nodeEnv === 'development') {
3232
// API routes (no version prefix for health checks)
3333
const api = new Hono();
3434

35-
// Health check (no auth required)
36-
api.get('/health', (c) => {
37-
return c.json({ status: 'ok', timestamp: new Date().toISOString() });
38-
});
39-
40-
// Postgate connection test (no auth required)
41-
api.get('/postgate', async (c) => {
42-
try {
43-
const result = await sql<{ result: number }>('SELECT 1 + 1 AS result');
44-
return c.json({ status: 'ok', result: result[0]?.result });
45-
} catch (error) {
46-
return c.json({ status: 'error', error: String(error) }, 500);
47-
}
48-
});
49-
50-
// Cron WASM test (no auth required)
51-
api.get('/cron-test', (c) => {
52-
const pattern = c.req.query('pattern') || '*/5 * * * *';
53-
try {
54-
const cron = new WasmCron(pattern);
55-
return c.json({
56-
status: 'ok',
57-
wasm: true,
58-
pattern: cron.pattern(),
59-
description: cron.describe(),
60-
nextRun: cron.nextRun()?.toISOString() ?? null,
61-
nextRuns: cron.nextRuns(5).map((d: Date) => d.toISOString())
62-
});
63-
} catch (error) {
64-
return c.json({ status: 'error', wasm: true, error: String(error) }, 400);
65-
}
66-
});
35+
// Health endpoints (no auth required)
36+
api.route('/health', health);
6737

6838
// API v1 routes
6939
const v1 = new Hono();

src/routes/health.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { Hono } from 'hono';
2+
3+
import { sql } from '../services/db/client';
4+
import { WasmCron } from '@openworkers/croner-wasm';
5+
6+
const health = new Hono();
7+
8+
// Liveness check
9+
health.get('/', (c) => {
10+
return c.json({ status: 'ok', timestamp: new Date().toISOString() });
11+
});
12+
13+
// Database connection test
14+
health.get('/database', async (c) => {
15+
try {
16+
const result = await sql<{ result: number }>('SELECT 1 + 1 AS result');
17+
return c.json({ status: 'ok', result: result[0]?.result });
18+
} catch (error) {
19+
return c.json({ status: 'error', error: String(error) }, 500);
20+
}
21+
});
22+
23+
// Cron WASM test
24+
health.get('/cron', (c) => {
25+
const pattern = c.req.query('pattern') || '*/5 * * * *';
26+
27+
try {
28+
const cron = new WasmCron(pattern);
29+
return c.json({
30+
status: 'ok',
31+
wasm: true,
32+
pattern: cron.pattern(),
33+
description: cron.describe(),
34+
nextRun: cron.nextRun()?.toISOString() ?? null,
35+
nextRuns: cron.nextRuns(5).map((d: Date) => d.toISOString())
36+
});
37+
} catch (error) {
38+
return c.json({ status: 'error', wasm: true, error: String(error) }, 400);
39+
}
40+
});
41+
42+
// --- Latency endpoints (used by CLI test-latency) ---
43+
44+
// API latency: measures request round-trip through all layers above
45+
health.get('/latency/api', (c) => {
46+
return c.json({ status: 'ok', timestamp: new Date().toISOString() });
47+
});
48+
49+
// Database latency: measures API + DB round-trip
50+
health.get('/latency/database', async (c) => {
51+
try {
52+
const result = await sql<{ now: string }>('SELECT NOW() AS now');
53+
return c.json({ status: 'ok', timestamp: result[0]?.now });
54+
} catch (error) {
55+
return c.json({ status: 'error', error: String(error) }, 500);
56+
}
57+
});
58+
59+
// Proxy latency: should be intercepted by Nginx before reaching API
60+
// If the CLI receives 418, it means Nginx is not intercepting this path
61+
health.get('/latency/proxy', (c) => {
62+
return c.json({ status: 'not_intercepted', layer: 'proxy' }, 418);
63+
});
64+
65+
export default health;

0 commit comments

Comments
 (0)