fix: normalize session ids for relay endpoints
- Normalize sessionId values to strings in relay handlers - Ensure recording endpoints pass string sessionId values - Stringify CLI sessionId before request body
This commit is contained in:
+52
-25
@@ -6,7 +6,16 @@ import { createNodeWebSocket } from '@hono/node-ws'
|
||||
import type { WSContext } from 'hono/ws'
|
||||
import type { Protocol } from './cdp-types.js'
|
||||
import type { CDPCommand, CDPResponseBase, CDPEventBase, CDPEventFor, RelayServerEvents } from './cdp-types.js'
|
||||
import type { ExtensionMessage, ExtensionEventMessage, RecordingDataMessage, RecordingCancelledMessage } from './protocol.js'
|
||||
import type {
|
||||
ExtensionMessage,
|
||||
ExtensionEventMessage,
|
||||
RecordingDataMessage,
|
||||
RecordingCancelledMessage,
|
||||
StartRecordingBody,
|
||||
StopRecordingParams,
|
||||
CancelRecordingParams,
|
||||
IsRecordingParams,
|
||||
} from './protocol.js'
|
||||
import pc from 'picocolors'
|
||||
import { EventEmitter } from 'node:events'
|
||||
import { VERSION, EXTENSION_IDS } from './utils.js'
|
||||
@@ -119,6 +128,14 @@ export async function startPlayWriterCDPRelayServer({
|
||||
return null
|
||||
}
|
||||
|
||||
const normalizeSessionId = (value: string | number | null | undefined): string | null => {
|
||||
if (value === undefined || value === null) {
|
||||
return null
|
||||
}
|
||||
const normalized = String(value)
|
||||
return normalized ? normalized : null
|
||||
}
|
||||
|
||||
const startExtensionPing = (extensionId: string): void => {
|
||||
const connection = extensionConnections.get(extensionId)
|
||||
if (!connection) {
|
||||
@@ -1285,8 +1302,9 @@ export async function startPlayWriterCDPRelayServer({
|
||||
|
||||
app.post('/cli/execute', async (c) => {
|
||||
try {
|
||||
const body = await c.req.json() as { sessionId: string; code: string; timeout?: number }
|
||||
const { sessionId, code, timeout = 10000 } = body
|
||||
const body = await c.req.json() as { sessionId: string | number; code: string; timeout?: number }
|
||||
const sessionId = normalizeSessionId(body.sessionId)
|
||||
const { code, timeout = 10000 } = body
|
||||
|
||||
if (!sessionId || !code) {
|
||||
return c.json({ error: 'sessionId and code are required' }, 400)
|
||||
@@ -1308,8 +1326,8 @@ export async function startPlayWriterCDPRelayServer({
|
||||
|
||||
app.post('/cli/reset', async (c) => {
|
||||
try {
|
||||
const body = await c.req.json() as { sessionId: string }
|
||||
const { sessionId } = body
|
||||
const body = await c.req.json() as { sessionId: string | number }
|
||||
const sessionId = normalizeSessionId(body.sessionId)
|
||||
|
||||
if (!sessionId) {
|
||||
return c.json({ error: 'sessionId is required' }, 400)
|
||||
@@ -1388,8 +1406,8 @@ export async function startPlayWriterCDPRelayServer({
|
||||
|
||||
app.post('/cli/session/delete', async (c) => {
|
||||
try {
|
||||
const body = await c.req.json() as { sessionId: string }
|
||||
const { sessionId } = body
|
||||
const body = await c.req.json() as { sessionId: string | number }
|
||||
const sessionId = normalizeSessionId(body.sessionId)
|
||||
|
||||
if (!sessionId) {
|
||||
return c.json({ error: 'sessionId is required' }, 400)
|
||||
@@ -1413,65 +1431,74 @@ export async function startPlayWriterCDPRelayServer({
|
||||
// ============================================================================
|
||||
|
||||
app.post('/recording/start', async (c) => {
|
||||
const body = await c.req.json() as { outputPath?: string; sessionId?: string; frameRate?: number; audio?: boolean; videoBitsPerSecond?: number; audioBitsPerSecond?: number }
|
||||
const body = await c.req.json() as { outputPath?: string; sessionId?: string | number; frameRate?: number; audio?: boolean; videoBitsPerSecond?: number; audioBitsPerSecond?: number }
|
||||
const sessionId = normalizeSessionId(body.sessionId)
|
||||
const { sessionId: _sessionId, ...recordingOptions } = body
|
||||
const manager = await getExecutorManager()
|
||||
const executor = body.sessionId ? manager.getSession(body.sessionId) : null
|
||||
if (body.sessionId && !executor) {
|
||||
return c.json({ success: false, error: `Session ${body.sessionId} not found` }, 404)
|
||||
const executor = sessionId ? manager.getSession(sessionId) : null
|
||||
if (sessionId && !executor) {
|
||||
return c.json({ success: false, error: `Session ${sessionId} not found` }, 404)
|
||||
}
|
||||
const extensionId = executor?.getSessionMetadata().extensionId || null
|
||||
const relay = getRecordingRelay(extensionId)
|
||||
if (!relay) {
|
||||
return c.json({ success: false, error: 'Extension not connected' }, 500)
|
||||
}
|
||||
const result = await relay.startRecording(body as { outputPath: string } & typeof body)
|
||||
const recordingParams = (sessionId ? { ...recordingOptions, sessionId } : recordingOptions) as StartRecordingBody
|
||||
const result = await relay.startRecording(recordingParams)
|
||||
const status = result.success ? 200 : (result.error?.includes('required') ? 400 : 500)
|
||||
return c.json(result, status)
|
||||
})
|
||||
|
||||
app.post('/recording/stop', async (c) => {
|
||||
const body = await c.req.json() as { sessionId?: string }
|
||||
const body = await c.req.json() as { sessionId?: string | number }
|
||||
const sessionId = normalizeSessionId(body.sessionId)
|
||||
const manager = await getExecutorManager()
|
||||
const executor = body.sessionId ? manager.getSession(body.sessionId) : null
|
||||
if (body.sessionId && !executor) {
|
||||
return c.json({ success: false, error: `Session ${body.sessionId} not found` }, 404)
|
||||
const executor = sessionId ? manager.getSession(sessionId) : null
|
||||
if (sessionId && !executor) {
|
||||
return c.json({ success: false, error: `Session ${sessionId} not found` }, 404)
|
||||
}
|
||||
const extensionId = executor?.getSessionMetadata().extensionId || null
|
||||
const relay = getRecordingRelay(extensionId)
|
||||
if (!relay) {
|
||||
return c.json({ success: false, error: 'Extension not connected' }, 500)
|
||||
}
|
||||
const result = await relay.stopRecording(body)
|
||||
const stopParams: StopRecordingParams = sessionId ? { sessionId } : {}
|
||||
const result = await relay.stopRecording(stopParams)
|
||||
const status = result.success ? 200 : (result.error?.includes('not found') ? 404 : 500)
|
||||
return c.json(result, status)
|
||||
})
|
||||
|
||||
app.get('/recording/status', async (c) => {
|
||||
const sessionId = c.req.query('sessionId')
|
||||
const sessionId = normalizeSessionId(c.req.query('sessionId'))
|
||||
const normalizedSessionId = sessionId || undefined
|
||||
const manager = await getExecutorManager()
|
||||
const executor = sessionId ? manager.getSession(sessionId) : null
|
||||
const executor = normalizedSessionId ? manager.getSession(normalizedSessionId) : null
|
||||
const extensionId = executor?.getSessionMetadata().extensionId || null
|
||||
const relay = getRecordingRelay(extensionId)
|
||||
if (!relay) {
|
||||
return c.json({ isRecording: false })
|
||||
}
|
||||
const result = await relay.isRecording({ sessionId })
|
||||
const isRecordingParams: IsRecordingParams = normalizedSessionId ? { sessionId: normalizedSessionId } : {}
|
||||
const result = await relay.isRecording(isRecordingParams)
|
||||
return c.json(result)
|
||||
})
|
||||
|
||||
app.post('/recording/cancel', async (c) => {
|
||||
const body = await c.req.json() as { sessionId?: string }
|
||||
const body = await c.req.json() as { sessionId?: string | number }
|
||||
const sessionId = normalizeSessionId(body.sessionId)
|
||||
const manager = await getExecutorManager()
|
||||
const executor = body.sessionId ? manager.getSession(body.sessionId) : null
|
||||
if (body.sessionId && !executor) {
|
||||
return c.json({ success: false, error: `Session ${body.sessionId} not found` }, 404)
|
||||
const executor = sessionId ? manager.getSession(sessionId) : null
|
||||
if (sessionId && !executor) {
|
||||
return c.json({ success: false, error: `Session ${sessionId} not found` }, 404)
|
||||
}
|
||||
const extensionId = executor?.getSessionMetadata().extensionId || null
|
||||
const relay = getRecordingRelay(extensionId)
|
||||
if (!relay) {
|
||||
return c.json({ success: false, error: 'Extension not connected' }, 500)
|
||||
}
|
||||
const result = await relay.cancelRecording(body)
|
||||
const cancelParams: CancelRecordingParams = sessionId ? { sessionId } : {}
|
||||
const result = await relay.cancelRecording(cancelParams)
|
||||
return c.json(result)
|
||||
})
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ async function executeCode(options: {
|
||||
}): Promise<void> {
|
||||
const { code, timeout, host, token } = options
|
||||
const cwd = process.cwd()
|
||||
const sessionId = options.sessionId || process.env.PLAYWRITER_SESSION
|
||||
const sessionId = options.sessionId ? String(options.sessionId) : process.env.PLAYWRITER_SESSION
|
||||
|
||||
// Session is required
|
||||
if (!sessionId) {
|
||||
|
||||
Reference in New Issue
Block a user