Fix bin/publish: use correct .env path for rspade_system Fix bin/publish script: prevent grep exit code 1 from terminating script 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
151 lines
4.6 KiB
TypeScript
Executable File
151 lines
4.6 KiB
TypeScript
Executable File
import express, { Request, Response } from 'express';
|
|
import * as http from 'http';
|
|
import { Config } from './utils/config';
|
|
import { Logger } from './utils/logger';
|
|
import { WebSocketHandler } from './http/websocket';
|
|
import { AuthValidator } from './http/auth';
|
|
|
|
class DebugProxyServer {
|
|
private app: express.Application;
|
|
private server: http.Server | null = null;
|
|
private logger: Logger;
|
|
private isShuttingDown: boolean = false;
|
|
private wsHandler: WebSocketHandler;
|
|
private authValidator: AuthValidator;
|
|
|
|
constructor() {
|
|
this.logger = new Logger('DebugProxyServer');
|
|
this.app = express();
|
|
this.authValidator = new AuthValidator();
|
|
this.wsHandler = new WebSocketHandler(this.authValidator);
|
|
this.setupMiddleware();
|
|
this.setupRoutes();
|
|
this.setupShutdownHandlers();
|
|
}
|
|
|
|
private setupMiddleware(): void {
|
|
// Parse JSON bodies
|
|
this.app.use(express.json());
|
|
|
|
// Request logging
|
|
this.app.use((req, _res, next) => {
|
|
this.logger.info(`${req.method} ${req.path}`);
|
|
next();
|
|
});
|
|
}
|
|
|
|
private setupRoutes(): void {
|
|
// Public endpoints (no auth)
|
|
this.app.get('/_ide/debug/status', (_req: Request, res: Response) => {
|
|
res.json({
|
|
status: 'healthy',
|
|
service: 'rspade-debug-proxy',
|
|
version: '1.0.0',
|
|
uptime: process.uptime(),
|
|
memory: process.memoryUsage()
|
|
});
|
|
});
|
|
|
|
// Ping endpoint for basic connectivity test
|
|
this.app.get('/_ide/debug/ping', (_req: Request, res: Response) => {
|
|
res.json({ pong: true });
|
|
});
|
|
|
|
// Authenticated endpoints
|
|
this.app.use('/_ide/debug/api', this.authValidator.authMiddleware());
|
|
|
|
this.app.post('/_ide/debug/api/test', (req: Request, res: Response) => {
|
|
const sessionId = (req as any).sessionId;
|
|
res.json({
|
|
success: true,
|
|
message: 'Authenticated successfully',
|
|
sessionId: sessionId
|
|
});
|
|
});
|
|
|
|
// 404 handler
|
|
this.app.use((req: Request, res: Response) => {
|
|
res.status(404).json({
|
|
error: 'Not Found',
|
|
path: req.path
|
|
});
|
|
});
|
|
|
|
// Error handler
|
|
this.app.use((err: Error, _req: Request, res: Response, _next: Function) => {
|
|
this.logger.error('Request error:', err);
|
|
res.status(500).json({
|
|
error: 'Internal Server Error',
|
|
message: err.message
|
|
});
|
|
});
|
|
}
|
|
|
|
private setupShutdownHandlers(): void {
|
|
const shutdown = async (signal: string) => {
|
|
if (this.isShuttingDown) {
|
|
return;
|
|
}
|
|
this.isShuttingDown = true;
|
|
|
|
this.logger.info(`Received ${signal}, starting graceful shutdown...`);
|
|
|
|
// Close HTTP server
|
|
if (this.server) {
|
|
this.server.close(() => {
|
|
this.logger.info('HTTP server closed');
|
|
});
|
|
}
|
|
|
|
// Give connections time to close
|
|
setTimeout(() => {
|
|
this.logger.info('Shutdown complete');
|
|
process.exit(0);
|
|
}, 5000);
|
|
};
|
|
|
|
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
}
|
|
|
|
public async start(): Promise<void> {
|
|
const port = Config.HTTP_PORT;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
this.server = this.app.listen(port, () => {
|
|
this.logger.info(`Debug proxy service started on port ${port}`);
|
|
this.logger.info(`Status endpoint: http://localhost:${port}/_ide/debug/status`);
|
|
this.logger.info(`WebSocket endpoint: ws://localhost:${port}/_ide/debug/ws`);
|
|
|
|
// Initialize WebSocket handler
|
|
this.wsHandler.initialize(this.server!);
|
|
this.logger.info('WebSocket handler initialized');
|
|
|
|
resolve();
|
|
});
|
|
|
|
this.server.on('error', (error: Error) => {
|
|
this.logger.error('Failed to start server:', error);
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
// Main entry point
|
|
async function main() {
|
|
const server = new DebugProxyServer();
|
|
|
|
try {
|
|
await server.start();
|
|
} catch (error) {
|
|
console.error('Failed to start debug proxy:', error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Start the server
|
|
main().catch(error => {
|
|
console.error('Uncaught error:', error);
|
|
process.exit(1);
|
|
}); |