Spaces:
Running
Running
File size: 2,990 Bytes
5dfbe50 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
import { serve } from '@hono/node-server';
import { Hono } from 'hono';
import { compress } from 'hono/compress';
import { secureHeaders } from 'hono/secure-headers';
import { timeout } from 'hono/timeout';
import { config } from './config';
import { corsMiddleware } from './middleware/cors';
import { loggerMiddleware, requestIdMiddleware } from './middleware/logger';
import { rateLimitMiddleware } from './middleware/rateLimit';
import { api } from './routes/api';
import { backendApi } from './routes/backend-api';
import { healthApp } from './routes/health';
const app = new Hono();
// Global middleware
app.use('*', requestIdMiddleware);
app.use('*', loggerMiddleware);
app.use('*', corsMiddleware);
app.use('*', secureHeaders());
app.use('*', compress());
// Apply rate limiting to API routes only
app.use('/api/*', rateLimitMiddleware);
// Apply timeout to prevent hanging requests (30 seconds, except for SSE)
app.use('/api/*', async (c, next) => {
if (c.req.path === '/api/chat') {
// Skip timeout for SSE endpoints
await next();
} else {
return timeout(30000)(c, next);
}
});
// Mount routes - matching backend API structure at root level
app.route('/', backendApi);
// Also mount at /api for direct Next.js API access (optional)
app.route('/api', api);
// Health check
app.route('/health', healthApp);
// Root info endpoint
app.get('/info', (c) => {
return c.json({
name: 'ColPali Hono Proxy',
version: '1.0.0',
endpoints: {
// Backend-compatible endpoints (Python API format)
search: '/fetch_results',
fullImage: '/full_image',
suggestions: '/suggestions',
similarityMaps: '/get_sim_map',
chat: '/get-message',
// Direct API endpoints
apiSearch: '/api/colpali-search',
apiFullImage: '/api/full-image',
apiSuggestions: '/api/query-suggestions',
apiSimilarityMaps: '/api/similarity-maps',
apiChat: '/api/visual-rag-chat',
health: '/health',
},
});
});
// 404 handler
app.notFound((c) => {
return c.json({ error: 'Not found', path: c.req.path }, 404);
});
// Global error handler
app.onError((err, c) => {
console.error(`Error handling request ${c.req.path}:`, err);
if (err instanceof Error) {
if (err.message.includes('timeout')) {
return c.json({ error: 'Request timeout' }, 408);
}
}
return c.json(
{
error: 'Internal server error',
requestId: c.get('requestId'),
},
500
);
});
// Start server
const port = config.port;
console.log(`π ColPali Hono Proxy starting...`);
console.log(`π Backend URL: ${config.backendUrl}`);
console.log(`π CORS Origin: ${config.corsOrigin}`);
console.log(`πΎ Cache: ${config.enableCache ? 'Enabled' : 'Disabled'}`);
console.log(`π¦ Rate Limit: ${config.rateLimit.max} requests per ${config.rateLimit.windowMs / 1000}s`);
serve({
fetch: app.fetch,
port,
}, (info) => {
console.log(`β
Server running on http://localhost:${info.port}`);
}); |