Spaces:
Running
Running
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}`); | |
}); |