mirror of
https://dev.azure.com/tstanciu94/PhantomMind/_git/Bitip
synced 2025-10-13 01:52:19 +03:00
feat: add health check endpoint for Docker compatibility
This commit is contained in:
parent
e53ccff95c
commit
bb19edd7e3
@ -109,6 +109,7 @@ ENABLE_HTTPS_SECURITY=false
|
|||||||
- Useful for reverse proxy scenarios or hosting multiple apps on same domain
|
- Useful for reverse proxy scenarios or hosting multiple apps on same domain
|
||||||
- **Example**: `/geoip-ui`
|
- **Example**: `/geoip-ui`
|
||||||
- **Note**: All API routes are prefixed with this path automatically
|
- **Note**: All API routes are prefixed with this path automatically
|
||||||
|
- **Health Check**: The `/api/health` endpoint is ALWAYS available at root (`/api/health`) for Docker HEALTHCHECK compatibility, AND also at `{BASE_PATH}/api/health` for consistency
|
||||||
|
|
||||||
**`NODE_ENV`**
|
**`NODE_ENV`**
|
||||||
|
|
||||||
|
35
src/backend/handlers/healthHandler.ts
Normal file
35
src/backend/handlers/healthHandler.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { Request, Response } from 'express';
|
||||||
|
import geoIPService from '../services/geoip.js';
|
||||||
|
import logger from '../services/logger.js';
|
||||||
|
|
||||||
|
export const healthCheckHandler = async (
|
||||||
|
_req: Request,
|
||||||
|
res: Response
|
||||||
|
): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const isHealthy = await geoIPService.healthCheck();
|
||||||
|
|
||||||
|
if (isHealthy) {
|
||||||
|
res.json({
|
||||||
|
status: 'healthy',
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
service: 'Bitip GeoIP Service',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.status(503).json({
|
||||||
|
status: 'unhealthy',
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
service: 'Bitip GeoIP Service',
|
||||||
|
error: 'GeoIP service health check failed',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Health check failed', error as Error);
|
||||||
|
res.status(503).json({
|
||||||
|
status: 'unhealthy',
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
service: 'Bitip GeoIP Service',
|
||||||
|
error: 'Health check endpoint failed',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
1
src/backend/handlers/index.ts
Normal file
1
src/backend/handlers/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './healthHandler.js';
|
@ -12,6 +12,7 @@ import dynamicRateLimit from './middleware/rateLimit.js';
|
|||||||
import config from './services/config.js';
|
import config from './services/config.js';
|
||||||
import logger from './services/logger.js';
|
import logger from './services/logger.js';
|
||||||
import { generateRuntimeConfig } from './services/runtimeConfig.js';
|
import { generateRuntimeConfig } from './services/runtimeConfig.js';
|
||||||
|
import { healthCheckHandler } from './handlers';
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename);
|
||||||
@ -76,6 +77,9 @@ const frontendPath = path.join(__dirname, '../frontend');
|
|||||||
// Generate runtime configuration (env.js) at startup
|
// Generate runtime configuration (env.js) at startup
|
||||||
generateRuntimeConfig(frontendPath, basePath);
|
generateRuntimeConfig(frontendPath, basePath);
|
||||||
|
|
||||||
|
// Health check endpoint at root (always accessible for Docker HEALTHCHECK)
|
||||||
|
app.get('/api/health', healthCheckHandler);
|
||||||
|
|
||||||
// API routes with authentication and rate limiting
|
// API routes with authentication and rate limiting
|
||||||
app.use(`${basePath}/api`, apiKeyAuth, dynamicRateLimit, apiRoutes);
|
app.use(`${basePath}/api`, apiKeyAuth, dynamicRateLimit, apiRoutes);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import { dirname, join } from 'path';
|
|||||||
import geoIPService from '../services/geoip.js';
|
import geoIPService from '../services/geoip.js';
|
||||||
import logger from '../services/logger.js';
|
import logger from '../services/logger.js';
|
||||||
import config from '../services/config.js';
|
import config from '../services/config.js';
|
||||||
|
import { healthCheckHandler } from '../handlers';
|
||||||
import {
|
import {
|
||||||
BatchGeoIPRequest,
|
BatchGeoIPRequest,
|
||||||
BatchGeoIPResponse,
|
BatchGeoIPResponse,
|
||||||
@ -252,34 +253,7 @@ router.post('/lookup/batch', async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Health check
|
// Health check
|
||||||
router.get('/health', async (req: Request, res: Response) => {
|
router.get('/health', healthCheckHandler);
|
||||||
try {
|
|
||||||
const isHealthy = await geoIPService.healthCheck();
|
|
||||||
|
|
||||||
if (isHealthy) {
|
|
||||||
res.json({
|
|
||||||
status: 'healthy',
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
service: 'Bitip GeoIP Service',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
res.status(503).json({
|
|
||||||
status: 'unhealthy',
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
service: 'Bitip GeoIP Service',
|
|
||||||
error: 'GeoIP service health check failed',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Health check failed', error as Error);
|
|
||||||
res.status(503).json({
|
|
||||||
status: 'unhealthy',
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
service: 'Bitip GeoIP Service',
|
|
||||||
error: 'Health check endpoint failed',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get app version
|
// Get app version
|
||||||
router.get('/version', (_req: Request, res: Response): void => {
|
router.get('/version', (_req: Request, res: Response): void => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user