{"record":{"id":"c1a51848db737bc5","repo":"musistudio/claude-code-router","slug":"connect-target-is-missing","errorCode":null,"errorMessage":"CONNECT target is missing.","messagePattern":"CONNECT target is missing\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/proxy/service.ts","lineNumber":1353,"sourceCode":"  return new URL(`${targetUrl.pathname}${targetUrl.search}`, `http://${gatewayHost}:${config.gateway.port}`);\n}\n\nfunction resolveRequestUrl(request: IncomingMessage, defaultProtocol: \"http:\" | \"https:\"): URL {\n  const rawUrl = request.url || \"/\";\n  if (/^https?:\\/\\//i.test(rawUrl)) {\n    return new URL(rawUrl);\n  }\n\n  const host = readHeader(request.headers.host);\n  if (!host) {\n    throw new Error(\"Proxy request is missing Host header.\");\n  }\n  return new URL(`${defaultProtocol}//${host}${rawUrl.startsWith(\"/\") ? rawUrl : `/${rawUrl}`}`);\n}\n\nfunction parseConnectTarget(value: string | undefined): { hostname: string; port: number } {\n  if (!value) {\n    throw new Error(\"CONNECT target is missing.\");\n  }\n  const parsed = new URL(`http://${value}`);\n  return {\n    hostname: parsed.hostname,\n    port: parsed.port ? Number(parsed.port) : 443\n  };\n}\n\nfunction proxyEndpoint(config: AppConfig): string {\n  const host = config.proxy.host === \"0.0.0.0\" ? \"127.0.0.1\" : config.proxy.host;\n  return `http://${host}:${config.proxy.port}`;\n}\n\nfunction sharedProxyEndpoint(config: AppConfig): string {\n  const host = config.gateway.host === \"0.0.0.0\" ? \"127.0.0.1\" : config.gateway.host;\n  return `http://${host}:${config.gateway.port}`;\n}\n","sourceCodeStart":1335,"sourceCodeEnd":1371,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/proxy/service.ts#L1335-L1371","documentation":"An HTTPS CONNECT request had no target in its request line. The CONNECT method requires 'host:port' as the request target; the proxy throws when request.url is undefined/empty.","triggerScenarios":"A client opens a CONNECT tunnel with an empty request target — raw socket clients that send 'CONNECT  HTTP/1.1', or a TLS connection mistakenly handled as CONNECT due to routing/proxy configuration.","commonSituations":"Pointing an HTTPS client directly (not via proxy) at the proxy port so bytes are misinterpreted; hand-written tunnel clients; proxies chained incorrectly sending CONNECT with no authority component.","solutions":["Ensure HTTPS clients use the proxy as an HTTP CONNECT proxy (https-proxy-agent / standard proxy settings), not a raw TLS endpoint","If writing a custom client, always send 'CONNECT host:port HTTP/1.1' with a non-empty authority","Verify the client's proxy configuration URL/port"],"exampleFix":"// before\nsocket.write(\"CONNECT  HTTP/1.1\\r\\n\\r\\n\"); // throws\n\n// after\nsocket.write(\"CONNECT example.com:443 HTTP/1.1\\r\\nHost: example.com:443\\r\\n\\r\\n\");","handlingStrategy":"validation","validationCode":"if (!req.url || !/^[^\\s:]+:\\d+$/.test(req.url)) {\n  socket.end(\"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\");\n  return;\n}","typeGuard":"function isValidConnectTarget(url: string | undefined): url is string {\n  return typeof url === \"string\" && /^[^\\s:]+:\\d+$/.test(url);\n}","tryCatchPattern":"try { await handleConnect(req, socket, head); } catch (e) { if (e.message.includes(\"CONNECT target\")) { socket.end(\"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\"); return; } throw e; }","preventionTips":["Use established proxy agents for HTTPS traffic","Reject malformed CONNECT early at the socket layer","Log malformed CONNECT targets to spot misconfigured clients"],"tags":["proxy","connect","https","tunnel","request-parsing"],"backgroundTag":"invalid-connect-target","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}