Skip to content

Commit ec3ccfe

Browse files
jirispilkaclaude
andauthored
refactor: guard dev server DELETE handler and fix port parsing (#1001)
Minor fixes + cleanup to the dev/standby test server (`src/dev_server.ts`); does not affect the hosted server. - DELETE handler wrapped in try/catch (like POST/GET) — a rejection no longer crashes the process - `PORT` falls back to 3001 for empty/non-numeric values - error logged under the `errMessage` key; dead duplicate session-id injection removed; single-value enums inlined 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 4488ad7 commit ec3ccfe

1 file changed

Lines changed: 16 additions & 24 deletions

File tree

src/dev_server.ts

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,6 @@ import { parseServerMode } from './utils/server_mode.js';
2323
// analytics. Still overridable by an explicit TELEMETRY_ENV (e.g. PROD) in the env.
2424
process.env.TELEMETRY_ENV ??= 'DEV';
2525

26-
enum TransportType {
27-
HTTP = 'HTTP',
28-
}
29-
30-
enum Routes {
31-
MCP = '/',
32-
}
33-
3426
/**
3527
* Extracts the Apify API token from the incoming request.
3628
*
@@ -52,7 +44,10 @@ function extractApiTokenFromRequest(req: Request): string | undefined {
5244
const tokenFromUrl = new URL(req.url ?? '', `http://${req.headers.host}`).searchParams.get('token');
5345
return tokenFromUrl || undefined;
5446
} catch (error) {
55-
log.softFail('Failed to parse request URL for token extraction', { url: req.url, error });
47+
log.softFail('Failed to parse request URL for token extraction', {
48+
url: req.url,
49+
errMessage: error instanceof Error ? error.message : String(error),
50+
});
5651
return undefined;
5752
}
5853
}
@@ -116,7 +111,7 @@ export function createExpressApp(): express.Express {
116111

117112
// express.json() middleware to parse JSON bodies, before the POST / route.
118113
app.use(express.json());
119-
app.post(Routes.MCP, async (req: Request, res: Response) => {
114+
app.post('/', async (req: Request, res: Response) => {
120115
log.info('Received MCP request:', req.body);
121116
try {
122117
// Check for existing session ID
@@ -126,11 +121,6 @@ export function createExpressApp(): express.Express {
126121
if (sessionId && transports[sessionId]) {
127122
// Reuse existing transport
128123
transport = transports[sessionId];
129-
// Inject session ID into request params for existing sessions
130-
if (req.body?.params) {
131-
req.body.params._meta ??= {};
132-
req.body.params._meta.mcpSessionId = sessionId;
133-
}
134124
} else if (!sessionId && isInitializeRequest(req.body)) {
135125
// Extract telemetry query parameters
136126
const urlParams = new URL(req.url, `http://${req.headers.host}`).searchParams;
@@ -197,7 +187,7 @@ export function createExpressApp(): express.Express {
197187
return;
198188
}
199189

200-
// Inject session ID into request params for all requests
190+
// Inject session ID into request params for the reused existing session
201191
if (req.body?.params && sessionId) {
202192
req.body.params._meta ??= {};
203193
req.body.params._meta.mcpSessionId = sessionId;
@@ -214,7 +204,7 @@ export function createExpressApp(): express.Express {
214204
// Clients open this to receive server-initiated notifications (e.g. notifications/tasks/status)
215205
// that are not tied to a specific POST request. Without this, session-level notifications
216206
// are silently dropped by the transport.
217-
app.get(Routes.MCP, async (req: Request, res: Response) => {
207+
app.get('/', async (req: Request, res: Response) => {
218208
const sessionId = req.headers['mcp-session-id'] as string | undefined;
219209
const transport = transports[sessionId || ''] as StreamableHTTPServerTransport | undefined;
220210
if (!transport) {
@@ -224,8 +214,7 @@ export function createExpressApp(): express.Express {
224214
}
225215
log.info('MCP API', {
226216
mth: req.method,
227-
rt: Routes.MCP,
228-
tr: TransportType.HTTP,
217+
rt: '/',
229218
mcpSessionId: sessionId,
230219
});
231220
try {
@@ -235,18 +224,21 @@ export function createExpressApp(): express.Express {
235224
}
236225
});
237226

238-
app.delete(Routes.MCP, async (req: Request, res: Response) => {
227+
app.delete('/', async (req: Request, res: Response) => {
239228
const sessionId = req.headers['mcp-session-id'] as string | undefined;
240229

241230
const transport = transports[sessionId || ''] as StreamableHTTPServerTransport | undefined;
242231
if (transport) {
243232
log.info('MCP API', {
244233
mth: req.method,
245-
rt: Routes.MCP,
246-
tr: TransportType.HTTP,
234+
rt: '/',
247235
mcpSessionId: sessionId,
248236
});
249-
await transport.handleRequest(req, res, req.body);
237+
try {
238+
await transport.handleRequest(req, res, req.body);
239+
} catch (error) {
240+
respondWithError(res, error, 'Error handling DELETE request');
241+
}
250242
return;
251243
}
252244

@@ -278,7 +270,7 @@ function isInitializeRequest(body: unknown): boolean {
278270

279271
if (process.argv[1] === fileURLToPath(import.meta.url)) {
280272
const HOST = process.env.HOST ?? 'http://localhost';
281-
const PORT = Number(process.env.PORT ?? 3001);
273+
const PORT = Number(process.env.PORT) || 3001;
282274

283275
const app = createExpressApp();
284276

0 commit comments

Comments
 (0)