// Shared by the REST API and HTTP/WebSocket API panels. /** The runtime endpoint as the browser can reach it, for building invoke URLs. */ export function invokeEndpoint(runtimeEndpoint?: string): string | null { if (!runtimeEndpoint) return null try { const endpoint = new URL(runtimeEndpoint) if (isDockerBridgeAddress(endpoint.hostname) && typeof window !== 'undefined') { endpoint.hostname = window.location.hostname } return endpoint.toString().replace(/\/$/, '') } catch { return runtimeEndpoint.replace(/\/$/, '') } } function isDockerBridgeAddress(hostname: string): boolean { const octets = hostname.split('.').map(Number) return octets.length === 4 && octets.every((octet) => Number.isInteger(octet) && octet >= 0 && octet <= 255) && octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 } export function parseHeaders(value: string): Record { let parsed: unknown try { parsed = JSON.parse(value || '{}') } catch { throw new Error('Request headers must be valid JSON.') } if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed) || Object.values(parsed).some((header) => typeof header !== 'string')) { throw new Error('Request headers must be a JSON object with string values.') } return parsed as Record } export function formatResponseBody(body: string): string { try { return JSON.stringify(JSON.parse(body), null, 2) } catch { return body || '(empty response body)' } }